curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/coding/write-batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"files": [
{
"content": "export default function About() {\n return <h1>About</h1>;\n}\n",
"file_path": "src/pages/About.jsx"
},
{
"content": "export default function Home() {\n return <h1>Home</h1>;\n}\n",
"file_path": "src/pages/Home.jsx"
}
]
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/coding/write-batch"
payload = { "files": [
{
"content": "export default function About() {
return <h1>About</h1>;
}
",
"file_path": "src/pages/About.jsx"
},
{
"content": "export default function Home() {
return <h1>Home</h1>;
}
",
"file_path": "src/pages/Home.jsx"
}
] }
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({
files: [
{
content: 'export default function About() {\n return <h1>About</h1>;\n}\n',
file_path: 'src/pages/About.jsx'
},
{
content: 'export default function Home() {\n return <h1>Home</h1>;\n}\n',
file_path: 'src/pages/Home.jsx'
}
]
})
};
fetch('https://app.base44.com/api/apps/{app_id}/coding/write-batch', 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}/coding/write-batch",
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([
'files' => [
[
'content' => 'export default function About() {
return <h1>About</h1>;
}
',
'file_path' => 'src/pages/About.jsx'
],
[
'content' => 'export default function Home() {
return <h1>Home</h1>;
}
',
'file_path' => 'src/pages/Home.jsx'
]
]
]),
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}/coding/write-batch"
payload := strings.NewReader("{\n \"files\": [\n {\n \"content\": \"export default function About() {\\n return <h1>About</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/About.jsx\"\n },\n {\n \"content\": \"export default function Home() {\\n return <h1>Home</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/Home.jsx\"\n }\n ]\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}/coding/write-batch")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"files\": [\n {\n \"content\": \"export default function About() {\\n return <h1>About</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/About.jsx\"\n },\n {\n \"content\": \"export default function Home() {\\n return <h1>Home</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/Home.jsx\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/coding/write-batch")
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 \"files\": [\n {\n \"content\": \"export default function About() {\\n return <h1>About</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/About.jsx\"\n },\n {\n \"content\": \"export default function Home() {\\n return <h1>Home</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/Home.jsx\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "6820f3a4e7b91d003c45a1f2",
"created_date": "2026-08-01T09:15:00",
"updated_date": "2026-08-02T14:30:00",
"created_by": "developer@example.com",
"organization_id": "67e0b12c4d8a3f005b21c9e4",
"app_type": "user_app",
"name": "My CRM",
"user_description": "A CRM to track leads and deals",
"logo_url": "https://storage.base44.com/6820f3a4e7b91d003c45a1f2/3f2504e0_logo.png",
"social_image_url": "https://storage.base44.com/6820f3a4e7b91d003c45a1f2/7c9e6679_social.png",
"public_settings": "public_with_login",
"auth_config": {
"enable_username_password": true,
"enable_google_login": true,
"enable_microsoft_login": false,
"enable_facebook_login": false,
"enable_apple_login": false
},
"hide_entity_created_by": true,
"is_remixable": false,
"main_branch_protected": false,
"slug": "my-crm-3c45a1f2",
"is_unpublished": false,
"last_deployed_at": "2026-08-02T14:30:00",
"screenshot_url": "https://storage.base44.com/screenshots/6820f3a4e7b91d003c45a1f2.png",
"preview_screenshot_url": "https://storage.base44.com/previews/6820f3a4e7b91d003c45a1f2.png",
"owner_id": "6706af53b9c1e2004a37d85f",
"status": {
"state": "ready",
"details": "Publishing app",
"request_id": "a1b2c3d4e5f67890abcdef12",
"last_updated_date": "2026-08-02T14:30:00Z",
"error_source": "build",
"paywall_context": {
"billing_organization_id": "67e0b12c4d8a3f005b21c9e4",
"user_id": "6706af53b9c1e2004a37d85f",
"evaluated_at": "2026-08-02T14:30:00Z"
}
},
"dev_environment_enabled": false
}Save several app files
Saves several files into the app in one call, the way the app editor does.
Send up to 50 files. Every path is validated before anything is written, so one bad path fails the whole batch with a 400 and leaves the app untouched. An empty files list is a 400 rather than a no-op.
This route never deploys, so it refuses backend code: a path under functions/ answers 422 rather than writing source that the live function wouldn’t match. Use Save an app file for those, one at a time, and this one for the frontend files a visual edit touches.
Internally this route can follow a feature branch, but the parameter that selects one isn’t part of the public API, so writes through this endpoint land on the app’s main line.
The response is the app document as it stands after the change, the same shape Get app returns.
curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/coding/write-batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"files": [
{
"content": "export default function About() {\n return <h1>About</h1>;\n}\n",
"file_path": "src/pages/About.jsx"
},
{
"content": "export default function Home() {\n return <h1>Home</h1>;\n}\n",
"file_path": "src/pages/Home.jsx"
}
]
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/coding/write-batch"
payload = { "files": [
{
"content": "export default function About() {
return <h1>About</h1>;
}
",
"file_path": "src/pages/About.jsx"
},
{
"content": "export default function Home() {
return <h1>Home</h1>;
}
",
"file_path": "src/pages/Home.jsx"
}
] }
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({
files: [
{
content: 'export default function About() {\n return <h1>About</h1>;\n}\n',
file_path: 'src/pages/About.jsx'
},
{
content: 'export default function Home() {\n return <h1>Home</h1>;\n}\n',
file_path: 'src/pages/Home.jsx'
}
]
})
};
fetch('https://app.base44.com/api/apps/{app_id}/coding/write-batch', 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}/coding/write-batch",
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([
'files' => [
[
'content' => 'export default function About() {
return <h1>About</h1>;
}
',
'file_path' => 'src/pages/About.jsx'
],
[
'content' => 'export default function Home() {
return <h1>Home</h1>;
}
',
'file_path' => 'src/pages/Home.jsx'
]
]
]),
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}/coding/write-batch"
payload := strings.NewReader("{\n \"files\": [\n {\n \"content\": \"export default function About() {\\n return <h1>About</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/About.jsx\"\n },\n {\n \"content\": \"export default function Home() {\\n return <h1>Home</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/Home.jsx\"\n }\n ]\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}/coding/write-batch")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"files\": [\n {\n \"content\": \"export default function About() {\\n return <h1>About</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/About.jsx\"\n },\n {\n \"content\": \"export default function Home() {\\n return <h1>Home</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/Home.jsx\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/coding/write-batch")
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 \"files\": [\n {\n \"content\": \"export default function About() {\\n return <h1>About</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/About.jsx\"\n },\n {\n \"content\": \"export default function Home() {\\n return <h1>Home</h1>;\\n}\\n\",\n \"file_path\": \"src/pages/Home.jsx\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "6820f3a4e7b91d003c45a1f2",
"created_date": "2026-08-01T09:15:00",
"updated_date": "2026-08-02T14:30:00",
"created_by": "developer@example.com",
"organization_id": "67e0b12c4d8a3f005b21c9e4",
"app_type": "user_app",
"name": "My CRM",
"user_description": "A CRM to track leads and deals",
"logo_url": "https://storage.base44.com/6820f3a4e7b91d003c45a1f2/3f2504e0_logo.png",
"social_image_url": "https://storage.base44.com/6820f3a4e7b91d003c45a1f2/7c9e6679_social.png",
"public_settings": "public_with_login",
"auth_config": {
"enable_username_password": true,
"enable_google_login": true,
"enable_microsoft_login": false,
"enable_facebook_login": false,
"enable_apple_login": false
},
"hide_entity_created_by": true,
"is_remixable": false,
"main_branch_protected": false,
"slug": "my-crm-3c45a1f2",
"is_unpublished": false,
"last_deployed_at": "2026-08-02T14:30:00",
"screenshot_url": "https://storage.base44.com/screenshots/6820f3a4e7b91d003c45a1f2.png",
"preview_screenshot_url": "https://storage.base44.com/previews/6820f3a4e7b91d003c45a1f2.png",
"owner_id": "6706af53b9c1e2004a37d85f",
"status": {
"state": "ready",
"details": "Publishing app",
"request_id": "a1b2c3d4e5f67890abcdef12",
"last_updated_date": "2026-08-02T14:30:00Z",
"error_source": "build",
"paywall_context": {
"billing_organization_id": "67e0b12c4d8a3f005b21c9e4",
"user_id": "6706af53b9c1e2004a37d85f",
"evaluated_at": "2026-08-02T14:30:00Z"
}
},
"dev_environment_enabled": false
}Authorizations
Personal access token, sent as Authorization: Bearer <token>. Each operation lists the permission it needs: read_only or full_access. A full-access token can call every operation. A read-only token can call only the operations that list read_only; anything else returns 403 read_only_credential_route_not_allowed.
Path Parameters
ID of the app whose code to change.
Body
The files to save, 1 to 50 of them. All are validated before any is written.
1 - 50 elementsShow child attributes
Show child attributes
Response
The app after the writes.
ID of the app.
"6820f3a4e7b91d003c45a1f2"
Time the app was created, as a UTC timestamp in ISO 8601 format.
"2026-08-01T09:15:00"
Time the app document was last written, as a UTC timestamp in ISO 8601 format.
"2026-08-02T14:30:00"
Email of the user who created the app.
"developer@example.com"
ID of the workspace the app belongs to.
"67e0b12c4d8a3f005b21c9e4"
Kind of app, set when it's created. One of user_app (a web app), user_agent (an AI agent), mobile_app (a native mobile app), user_game (a game), slide (a presentation), or imported_app (an app imported from an existing code repository). List apps returns it as stored, so an older agent app can report agent instead of user_agent, and some older apps don't include it. Get app always returns one of the values above.
"user_app"
Display name of the app.
"My CRM"
Description of the app, or null if none was set. An app created without a name gets a generated description once a build turn changes it.
"A CRM to track leads and deals"
URL of the app's logo, or null if it has none. Set it with Set app logo or Generate app logo.
"https://storage.base44.com/6820f3a4e7b91d003c45a1f2/3f2504e0_logo.png"
URL of the image shown when the app is shared on social platforms, or null if none was set, in which case the logo is shown instead. Set it with Set social image.
"https://storage.base44.com/6820f3a4e7b91d003c45a1f2/7c9e6679_social.png"
Who can open the published app. Each value is described under Update app, which also changes it.
private_with_login, public_with_login, public_without_login, workspace_with_login "public_with_login"
Which login methods the app's login page offers. If the workspace enforces SSO for apps, the login page offers only SSO, whatever these are set to. Change them with Update app.
Show child attributes
Show child attributes
Whether the app's entity records leave out the email of the user who created each one (created_by). Newer apps always leave the email out, whatever this is set to.
true
Whether others can remix the app. While it's true, the published app also shows the Base44 badge if public_settings is public_with_login or public_without_login.
false
Whether the app's main branch is protected, so changes to main must go through a branch that's merged back. Always true for imported apps. Change it with Set main branch protection.
false
URL slug for the app, auto generated from the name and app ID or set to a custom value, or null if the app has no slug yet. The published URL is built from it.
"my-crm-3c45a1f2"
Whether the app was taken offline with Unpublish app and hasn't been published again since. While it's true, the published URL is offline and last_deployed_at still shows the last publish.
false
Time the app was last published, as a UTC timestamp in ISO 8601 format, or null if it has never been published.
"2026-08-02T14:30:00"
URL of a screenshot of the published app. Captured shortly after each publish, so it can briefly lag or be null right after publishing.
"https://storage.base44.com/screenshots/6820f3a4e7b91d003c45a1f2.png"
URL of a preview screenshot taken before publishing, distinct from screenshot_url, or null if none has been captured.
"https://storage.base44.com/previews/6820f3a4e7b91d003c45a1f2.png"
ID of the user who owns the app. It starts as the creator and changes when ownership is transferred.
"6706af53b9c1e2004a37d85f"
The app's current build status. Poll while a build is in progress to watch it finish. This tracks building, not publishing.
Show child attributes
Show child attributes
Whether test data is on, which gives the app a test database next to its live one.
false
Was this page helpful?