curl --request PATCH \
--url https://app.base44.com/api/apps/{app_id}/metadata/slug \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"slug": "nordwind-furniture"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/metadata/slug"
payload = { "slug": "nordwind-furniture" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({slug: 'nordwind-furniture'})
};
fetch('https://app.base44.com/api/apps/{app_id}/metadata/slug', 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}/metadata/slug",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'slug' => 'nordwind-furniture'
]),
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}/metadata/slug"
payload := strings.NewReader("{\n \"slug\": \"nordwind-furniture\"\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://app.base44.com/api/apps/{app_id}/metadata/slug")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"slug\": \"nordwind-furniture\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/metadata/slug")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"slug\": \"nordwind-furniture\"\n}"
response = http.request(request)
puts response.read_body{
"created_by": "developer@example.com",
"created_date": "2026-08-01T09:15:00",
"first_prompt_model_comparison": {
"client_creation_id": "<string>",
"id": "<string>",
"models": [
"<string>"
],
"status": "preparing"
},
"id": "6820f3a4e7b91d003c45a1f2",
"last_deployed_at": "2026-08-02T14:30:00",
"name": "My CRM",
"preview_screenshot_url": "https://storage.base44.com/previews/6820f3a4e7b91d003c45a1f2.png",
"screenshot_url": "https://storage.base44.com/screenshots/6820f3a4e7b91d003c45a1f2.png",
"slug": "my-crm-3c45a1f2",
"status": {
"state": "ready",
"details": "Publishing app",
"error_source": "build",
"last_updated_date": "2026-08-02T14:30:00Z",
"paywall_context": {
"billing_organization_id": "67e0b12c4d8a3f005b21c9e4",
"evaluated_at": "2026-08-02T14:30:00Z",
"user_id": "6706af53b9c1e2004a37d85f"
},
"request_id": "a1b2c3d4e5f67890abcdef12"
},
"updated_date": "2026-08-02T14:30:00",
"user_description": "A CRM to track leads and deals"
}{
"detail": "URL slug 'nordwind' is already in use",
"suggestions": [
"nordwind-furniture",
"nordwind-shop"
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Change app slug
Changes the app’s slug, which sets its <slug>.base44.app address.
Send null to reset the slug to the one Base44 generates from the app’s name and ID. Sending the current slug, in any capitalization, changes nothing.
An app listed on Launchpad can’t change its slug while a voting round is live, because the slug is also the listing’s public URL.
Changing the slug is limited to 30 requests an hour per caller. Some workspaces have a different limit.
curl --request PATCH \
--url https://app.base44.com/api/apps/{app_id}/metadata/slug \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"slug": "nordwind-furniture"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/metadata/slug"
payload = { "slug": "nordwind-furniture" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({slug: 'nordwind-furniture'})
};
fetch('https://app.base44.com/api/apps/{app_id}/metadata/slug', 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}/metadata/slug",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'slug' => 'nordwind-furniture'
]),
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}/metadata/slug"
payload := strings.NewReader("{\n \"slug\": \"nordwind-furniture\"\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://app.base44.com/api/apps/{app_id}/metadata/slug")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"slug\": \"nordwind-furniture\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/metadata/slug")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"slug\": \"nordwind-furniture\"\n}"
response = http.request(request)
puts response.read_body{
"created_by": "developer@example.com",
"created_date": "2026-08-01T09:15:00",
"first_prompt_model_comparison": {
"client_creation_id": "<string>",
"id": "<string>",
"models": [
"<string>"
],
"status": "preparing"
},
"id": "6820f3a4e7b91d003c45a1f2",
"last_deployed_at": "2026-08-02T14:30:00",
"name": "My CRM",
"preview_screenshot_url": "https://storage.base44.com/previews/6820f3a4e7b91d003c45a1f2.png",
"screenshot_url": "https://storage.base44.com/screenshots/6820f3a4e7b91d003c45a1f2.png",
"slug": "my-crm-3c45a1f2",
"status": {
"state": "ready",
"details": "Publishing app",
"error_source": "build",
"last_updated_date": "2026-08-02T14:30:00Z",
"paywall_context": {
"billing_organization_id": "67e0b12c4d8a3f005b21c9e4",
"evaluated_at": "2026-08-02T14:30:00Z",
"user_id": "6706af53b9c1e2004a37d85f"
},
"request_id": "a1b2c3d4e5f67890abcdef12"
},
"updated_date": "2026-08-02T14:30:00",
"user_description": "A CRM to track leads and deals"
}{
"detail": "URL slug 'nordwind' is already in use",
"suggestions": [
"nordwind-furniture",
"nordwind-shop"
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Authorizations
Personal access token, sent as Authorization: Bearer <token>.
Path Parameters
ID of the app.
Body
New slug, 3 to 50 characters of letters, numbers, and hyphens that starts and ends with a letter or number. It has to be unused by any other app and not a reserved name, and it's lowercased before it's saved. Send null to reset it to the slug Base44 generates from the app's name and ID.
"nordwind-furniture"
Response
The app, with its new slug.
An app in a workspace, limited to the properties the caller requested.
Email of the user who created the app.
"developer@example.com"
Time the app was created, as a UTC timestamp in ISO 8601 format.
"2026-08-01T09:15:00"
Accepted first-prompt model comparison, including its durable comparison ID.
Show child attributes
Show child attributes
ID of the app.
"6820f3a4e7b91d003c45a1f2"
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"
Display name of the app.
"My CRM"
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"
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 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"
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
Time the app document was last written, as a UTC timestamp in ISO 8601 format.
"2026-08-02T14:30:00"
Description of the app, or null if none was set. On a newly created app this holds the original prompt text.
"A CRM to track leads and deals"
Was this page helpful?