curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/batch \
--header 'Content-Type: application/json' \
--header 'api_key: <api-key>' \
--data '
{
"tool_call_ids": [
"toolu_01A9FJd3kP2mNqRs7VwXyZ4b"
],
"action": "approved"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/batch"
payload = {
"tool_call_ids": ["toolu_01A9FJd3kP2mNqRs7VwXyZ4b"],
"action": "approved"
}
headers = {
"api_key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {api_key: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({tool_call_ids: ['toolu_01A9FJd3kP2mNqRs7VwXyZ4b'], action: 'approved'})
};
fetch('https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/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}/chat/submit-tool-call-input/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([
'tool_call_ids' => [
'toolu_01A9FJd3kP2mNqRs7VwXyZ4b'
],
'action' => 'approved'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/batch"
payload := strings.NewReader("{\n \"tool_call_ids\": [\n \"toolu_01A9FJd3kP2mNqRs7VwXyZ4b\"\n ],\n \"action\": \"approved\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("api_key", "<api-key>")
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}/chat/submit-tool-call-input/batch")
.header("api_key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"tool_call_ids\": [\n \"toolu_01A9FJd3kP2mNqRs7VwXyZ4b\"\n ],\n \"action\": \"approved\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["api_key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"tool_call_ids\": [\n \"toolu_01A9FJd3kP2mNqRs7VwXyZ4b\"\n ],\n \"action\": \"approved\"\n}"
response = http.request(request)
puts response.read_body{
"results": [
{
"id": "toolu_01A9FJd3kP2mNqRs7VwXyZ4b",
"success": true,
"error": "Failed to process tool call"
}
],
"app": {
"id": "6820f3a4e7b91d003c45a1f2",
"name": "My CRM",
"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"
}
},
"conversation": {
"id": "1f0c2b7a-9d51-4c3e-8a62-7b4d5e6f8a90",
"messages": [
{
"id": "7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19",
"role": "assistant",
"content": "I added a contact form to the home page.",
"file_urls": [
"https://example.com/mockup.png"
],
"hidden": false,
"checkpoint_id": "6886b8d390dc7e2f4a2c91b3",
"tool_calls": [
{
"id": "toolu_01A9FJd3kP2mNqRs7VwXyZ4b",
"name": "create_file",
"status": "waiting_for_user_input",
"requires_user_input": true,
"arguments_string": "{\"file_path\": \"src/pages/Home.jsx\", \"content\": \"export default function Home() {}\"}"
}
],
"usage": {
"prompt_tokens": 18432,
"completion_tokens": 742,
"credits_charged": 1.5
},
"metadata": {
"created_date": "2026-08-02T14:30:00",
"created_by_email": "developer@example.com"
}
}
]
}
}
}Submit tool-call input (batch)
Answers several waiting tool calls at once with the same action, then resumes the turn. Use it instead of calling Submit tool-call input once per tool call.
Each tool call gets its own entry in results, so one of them can fail while the rest succeed. Check every entry rather than assuming the whole batch worked. The app is returned under app, not at the top level as it is on the single-tool-call endpoint.
The request stays open until the resumed turn settles, so it can take several minutes. Resuming a turn consumes credits.
Set an X-Request-ID header before you send. A network retry carrying the same value is ignored rather than resumed a second time and charged again. It comes back with an empty results array, which means nothing ran again rather than that the tool calls were rejected.
A 200 response does not mean the turn succeeded. Two cases come back as a 200.
- The turn ran and finished.
app.status.stateisreadyand the app is idle again. - The turn ran and failed.
app.status.stateiserror, andapp.status.error_sourcesays where it failed. A value ofpaywallmeans the app’s workspace has no credits left.
curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/batch \
--header 'Content-Type: application/json' \
--header 'api_key: <api-key>' \
--data '
{
"tool_call_ids": [
"toolu_01A9FJd3kP2mNqRs7VwXyZ4b"
],
"action": "approved"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/batch"
payload = {
"tool_call_ids": ["toolu_01A9FJd3kP2mNqRs7VwXyZ4b"],
"action": "approved"
}
headers = {
"api_key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {api_key: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({tool_call_ids: ['toolu_01A9FJd3kP2mNqRs7VwXyZ4b'], action: 'approved'})
};
fetch('https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/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}/chat/submit-tool-call-input/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([
'tool_call_ids' => [
'toolu_01A9FJd3kP2mNqRs7VwXyZ4b'
],
'action' => 'approved'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/batch"
payload := strings.NewReader("{\n \"tool_call_ids\": [\n \"toolu_01A9FJd3kP2mNqRs7VwXyZ4b\"\n ],\n \"action\": \"approved\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("api_key", "<api-key>")
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}/chat/submit-tool-call-input/batch")
.header("api_key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"tool_call_ids\": [\n \"toolu_01A9FJd3kP2mNqRs7VwXyZ4b\"\n ],\n \"action\": \"approved\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/chat/submit-tool-call-input/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["api_key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"tool_call_ids\": [\n \"toolu_01A9FJd3kP2mNqRs7VwXyZ4b\"\n ],\n \"action\": \"approved\"\n}"
response = http.request(request)
puts response.read_body{
"results": [
{
"id": "toolu_01A9FJd3kP2mNqRs7VwXyZ4b",
"success": true,
"error": "Failed to process tool call"
}
],
"app": {
"id": "6820f3a4e7b91d003c45a1f2",
"name": "My CRM",
"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"
}
},
"conversation": {
"id": "1f0c2b7a-9d51-4c3e-8a62-7b4d5e6f8a90",
"messages": [
{
"id": "7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19",
"role": "assistant",
"content": "I added a contact form to the home page.",
"file_urls": [
"https://example.com/mockup.png"
],
"hidden": false,
"checkpoint_id": "6886b8d390dc7e2f4a2c91b3",
"tool_calls": [
{
"id": "toolu_01A9FJd3kP2mNqRs7VwXyZ4b",
"name": "create_file",
"status": "waiting_for_user_input",
"requires_user_input": true,
"arguments_string": "{\"file_path\": \"src/pages/Home.jsx\", \"content\": \"export default function Home() {}\"}"
}
],
"usage": {
"prompt_tokens": 18432,
"completion_tokens": 742,
"credits_charged": 1.5
},
"metadata": {
"created_date": "2026-08-02T14:30:00",
"created_by_email": "developer@example.com"
}
}
]
}
}
}Authorizations
Personal API key.
Path Parameters
ID of the app whose AI chat this request acts on.
Body
IDs of the tool calls to answer, up to 100. They all get the same action, and a repeated ID is answered once.
[
"toolu_01A9FJd3kP2mNqRs7VwXyZ4b",
"toolu_01B8GKe4lQ3nOrSt8WxYzA5c"
]
Whether to let these tool calls run or turn them down.
approved, rejected "approved"
Response
Successful Response
The app after a batch of tool calls was answered, with one result per call.
One entry per tool call that was answered, in the order they were processed. A repeated ID appears once, so this can be shorter than the list you sent. Empty when the request was a duplicate that had already been applied.
Show child attributes
Show child attributes
The app once the resumed turn finished.
Show child attributes
Show child attributes
Was this page helpful?