curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/sandbox-bridge/grep \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"pattern": "useState",
"path": "src",
"glob": "*.jsx",
"max_results": 50
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/sandbox-bridge/grep"
payload = {
"pattern": "useState",
"path": "src",
"glob": "*.jsx",
"max_results": 50
}
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({pattern: 'useState', path: 'src', glob: '*.jsx', max_results: 50})
};
fetch('https://app.base44.com/api/apps/{app_id}/sandbox-bridge/grep', 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-bridge/grep",
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([
'pattern' => 'useState',
'path' => 'src',
'glob' => '*.jsx',
'max_results' => 50
]),
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}/sandbox-bridge/grep"
payload := strings.NewReader("{\n \"pattern\": \"useState\",\n \"path\": \"src\",\n \"glob\": \"*.jsx\",\n \"max_results\": 50\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}/sandbox-bridge/grep")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"pattern\": \"useState\",\n \"path\": \"src\",\n \"glob\": \"*.jsx\",\n \"max_results\": 50\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/sandbox-bridge/grep")
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 \"pattern\": \"useState\",\n \"path\": \"src\",\n \"glob\": \"*.jsx\",\n \"max_results\": 50\n}"
response = http.request(request)
puts response.read_body{
"matches": [
{
"line": 2,
"path": "src/pages/Home.jsx",
"text": " return <h1>Hello</h1>;"
}
],
"truncated": false,
"returned_matches": 1
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Search app files
Searches the app’s files for a pattern and returns the matching lines.
Every sandbox-bridge endpoint runs against the app’s live sandbox, the same filesystem the AI edits, so a change here is visible in the app editor immediately.
The pattern is a regular expression by default; set is_regex: false to match it literally. Narrow the search with path to a subtree and glob to a filename pattern. Matching is case-insensitive unless you set case_sensitive.
Finding nothing is a 200 with an empty matches, not a 404. Results are capped at max_results (200 by default, 1000 at most) and the output at 1 MB, and truncated tells you when either cap bit, so treat a true there as “narrow the search” rather than “no more matches”.
Base44 keeps its own protected trees out of the results, so a pattern that exists only there returns nothing.
This endpoint is limited to 120 requests per minute per app, shared with the other sandbox-bridge endpoints that only read.
CREDITS_EXHAUSTED. Otherwise the bridge needs a Builder plan or higher on the app’s workspace, and answers 402 below that (PREMIUM_REQUIRED). Workspace API keys are not authorized and are rejected with a 403, and it is unavailable for agent apps. A personal API key works as-is. An OAuth access token needs the apps:read scope; the read endpoints don’t require sandbox:write.extra_data.code alongside the human-readable message. Branch on the code rather than on the message text or the status.curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/sandbox-bridge/grep \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"pattern": "useState",
"path": "src",
"glob": "*.jsx",
"max_results": 50
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/sandbox-bridge/grep"
payload = {
"pattern": "useState",
"path": "src",
"glob": "*.jsx",
"max_results": 50
}
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({pattern: 'useState', path: 'src', glob: '*.jsx', max_results: 50})
};
fetch('https://app.base44.com/api/apps/{app_id}/sandbox-bridge/grep', 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-bridge/grep",
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([
'pattern' => 'useState',
'path' => 'src',
'glob' => '*.jsx',
'max_results' => 50
]),
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}/sandbox-bridge/grep"
payload := strings.NewReader("{\n \"pattern\": \"useState\",\n \"path\": \"src\",\n \"glob\": \"*.jsx\",\n \"max_results\": 50\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}/sandbox-bridge/grep")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"pattern\": \"useState\",\n \"path\": \"src\",\n \"glob\": \"*.jsx\",\n \"max_results\": 50\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/sandbox-bridge/grep")
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 \"pattern\": \"useState\",\n \"path\": \"src\",\n \"glob\": \"*.jsx\",\n \"max_results\": 50\n}"
response = http.request(request)
puts response.read_body{
"matches": [
{
"line": 2,
"path": "src/pages/Home.jsx",
"text": " return <h1>Hello</h1>;"
}
],
"truncated": false,
"returned_matches": 1
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}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 sandbox to operate on.
Body
Search pattern.
Optional Base44 branch ID. Omit to operate on main.
Subtree to search, relative to the app root. Default: whole app.
Treat the pattern as a regex (default) or a literal string.
Case-sensitive match. Default false.
Optional file glob filter, e.g. "*.tsx".
Maximum number of match lines to return.
1 <= x <= 1000Response
The matching lines, empty when nothing matched.
The matches, and whether you got all of them.
Matching lines, capped at max_results.
Show child attributes
Show child attributes
[
{
"line": 2,
"path": "src/pages/Home.jsx",
"text": " return <h1>Hello</h1>;"
}
]
true when there was more to return: either more matches than max_results, or output that hit the 1 MB cap. One very long line can set this with few matches.
false
How many entries matches holds.
1
Was this page helpful?