curl --request GET \
--url https://app.base44.com/api/apps/{app_id}/sandbox/preview-url \
--header 'api_key: <api-key>'import requests
url = "https://app.base44.com/api/apps/{app_id}/sandbox/preview-url"
headers = {"api_key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {api_key: '<api-key>'}};
fetch('https://app.base44.com/api/apps/{app_id}/sandbox/preview-url', 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}/sandbox/preview-url",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"api_key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/sandbox/preview-url"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("api_key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.base44.com/api/apps/{app_id}/sandbox/preview-url")
.header("api_key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/sandbox/preview-url")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["api_key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"preview_url": "https://preview-6820f3a4e7b91d003c45a1f2.base44.app",
"sandbox_info": {
"cold_start": false,
"restored_from_snapshot": false,
"timeout_timestamp": "2026-08-02T15:30:00"
},
"preview_token": "pv_8f2c1a9d4b7e",
"bridge_injected": true
}Get preview URL
Returns a URL that serves the app as it currently stands in the app editor, including changes that haven’t been published yet. Use it to look at your work in progress. Use Deploy an app to put it in front of your users.
The preview is served by a sandbox that shuts down when it goes unused. If none is running, this starts one, so the first call after a quiet period takes noticeably longer than later ones. The sandbox_info.cold_start field tells you which happened.
A 409 usually means the app’s code doesn’t currently build. The response body says what failed, so send that to the AI with Send chat message and ask for the preview again.
curl --request GET \
--url https://app.base44.com/api/apps/{app_id}/sandbox/preview-url \
--header 'api_key: <api-key>'import requests
url = "https://app.base44.com/api/apps/{app_id}/sandbox/preview-url"
headers = {"api_key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {api_key: '<api-key>'}};
fetch('https://app.base44.com/api/apps/{app_id}/sandbox/preview-url', 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}/sandbox/preview-url",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"api_key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/sandbox/preview-url"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("api_key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.base44.com/api/apps/{app_id}/sandbox/preview-url")
.header("api_key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/sandbox/preview-url")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["api_key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"preview_url": "https://preview-6820f3a4e7b91d003c45a1f2.base44.app",
"sandbox_info": {
"cold_start": false,
"restored_from_snapshot": false,
"timeout_timestamp": "2026-08-02T15:30:00"
},
"preview_token": "pv_8f2c1a9d4b7e",
"bridge_injected": true
}Authorizations
Personal API key.
Path Parameters
Response
Successful Response
A preview URL for an app, and the sandbox serving it.
URL that serves the app as it currently stands in the app editor, including changes that haven't been published. Open it in a browser or an iframe.
"https://preview-6820f3a4e7b91d003c45a1f2.base44.app"
Details of the sandbox serving this preview, including whether it had to be started for this request.
Show child attributes
Show child attributes
Short-lived token the preview URL needs to authenticate against the preview proxy. Treat it as a credential and don't share it, because anyone holding it can load the app before it is published.
"pv_8f2c1a9d4b7e"
Whether the preview host injects the builder bridge. False when the platform proxy is disabled and the preview falls back to the sandbox's own host, so the editor knows the bridge's mount/paint signals will never arrive and must not wait for them.
Was this page helpful?