curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/imported/session-imports \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form file=@example-file \
--form source_branch=fix-login-redirectimport requests
url = "https://app.base44.com/api/apps/{app_id}/imported/session-imports"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = { "source_branch": "fix-login-redirect" }
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', '<string>');
form.append('source_branch', 'fix-login-redirect');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://app.base44.com/api/apps/{app_id}/imported/session-imports', 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}/imported/session-imports",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_branch\"\r\n\r\nfix-login-redirect\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$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}/imported/session-imports"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_branch\"\r\n\r\nfix-login-redirect\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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}/imported/session-imports")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_branch\"\r\n\r\nfix-login-redirect\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/imported/session-imports")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_branch\"\r\n\r\nfix-login-redirect\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"branch_id": "6820f3a4e7b91d003c45a1f3",
"branch_name": "fix-login-redirect",
"source": "claude_code",
"turn_count": 42,
"branch_url": "/apps/6820f3a4e7b91d003c45a1f1/editor/preview?branch=fix-login-redirect",
"continued": true,
"source_ref": "fix-login-redirect"
}Import a Claude Code or Codex session
Imports a Claude Code or Codex session into an imported app as a Base Code branch, with the session’s conversation in that branch’s chat. You continue the work there with the AI. The base44 sessions import CLI command calls this endpoint.
Send the session file as file in a multipart/form-data body. Base Code reads a Claude Code transcript, the .jsonl file under ~/.claude/projects/, or a Codex rollout, the rollout-*.jsonl file under ~/.codex/sessions/. The file can be up to 25 MB.
The conversation is cut at the prompt that asked for the import, so that prompt and everything after it are left out. Only typed messages and the AI’s replies are kept, and at most the newest 400 turns are written. Thinking, tool arguments, and tool output are dropped.
The session continues on its own branch when that branch is in the app’s GitHub repository and isn’t the default branch. Base Code adopts that branch as it is, so stop working on it locally. If Base Code already has an active branch with that name, the import is refused and nothing is written. In every other case Base Code creates a new branch named after the session’s first message. It starts from the session’s branch when that’s in the repository, and from the default branch when it isn’t. continued and source_ref say which one happened.
Authenticate with a personal access token, sent as Authorization: Bearer <token>. Where the user isn’t signed in, such as on a cloud machine, send the one-time import key that Base Code’s Import session dialog creates in its place. The key starts with b44imp_, works once and only for the app it was created for, and expires after 10 minutes. The import then runs as the user who opened the dialog.
Send an Idempotency-Key header, such as a UUID, and repeat it when you retry after a lost response, a 409 conflict, or a 5xx. A retry with the same key, file, and source_branch returns the first import’s response and writes nothing. Only a successful import is remembered, for 24 hours, so a retry after an error imports again. An upload with an import key can’t be retried at all: the key works once, so a retry gets a 401.
curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/imported/session-imports \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form file=@example-file \
--form source_branch=fix-login-redirectimport requests
url = "https://app.base44.com/api/apps/{app_id}/imported/session-imports"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = { "source_branch": "fix-login-redirect" }
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', '<string>');
form.append('source_branch', 'fix-login-redirect');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://app.base44.com/api/apps/{app_id}/imported/session-imports', 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}/imported/session-imports",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_branch\"\r\n\r\nfix-login-redirect\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$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}/imported/session-imports"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_branch\"\r\n\r\nfix-login-redirect\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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}/imported/session-imports")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_branch\"\r\n\r\nfix-login-redirect\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/imported/session-imports")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_branch\"\r\n\r\nfix-login-redirect\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"branch_id": "6820f3a4e7b91d003c45a1f3",
"branch_name": "fix-login-redirect",
"source": "claude_code",
"turn_count": 42,
"branch_url": "/apps/6820f3a4e7b91d003c45a1f1/editor/preview?branch=fix-login-redirect",
"continued": true,
"source_ref": "fix-login-redirect"
}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.
Headers
A value you generate for this import, 8 to 100 characters, such as a UUID. Send the same value when you retry the import, and a new one for every other import. A retry with the same value, file, and source_branch within 24 hours returns the first response instead of importing again. Keys are scoped to the user and the app.
8 - 100Path Parameters
ID of the imported app to import the session into.
Body
A Claude Code or Codex session to import.
The session file, a Claude Code .jsonl transcript or a Codex rollout-*.jsonl file of up to 25 MB.
The Git branch the session is on now. It wins over the branch recorded in the file, which can predate a push. Leave it out to use the file's branch.
255"fix-login-redirect"
Response
The branch the session was imported into.
ID of the Base Code branch the session was imported into.
"6820f3a4e7b91d003c45a1f3"
Name of that branch. When continued is true, it's the session's own Git branch.
"fix-login-redirect"
The tool that recorded the session. Either "claude_code" or "codex".
claude_code, codex "claude_code"
Number of messages written to the branch's chat.
42
Path of the branch in the app editor. Append it to the Base44 address to open it.
"/apps/6820f3a4e7b91d003c45a1f1/editor/preview?branch=fix-login-redirect"
Whether the session continues on its own branch. The value is true when Base Code adopted the session's branch and false when it created a new branch from source_ref.
true
Git branch the Base Code branch comes from. It's the session's branch when that's in the repository, and the repository's default branch when it isn't.
"fix-login-redirect"
Was this page helpful?