curl --request POST \
--url https://app.base44.com/api/billing/create-checkout-session/{price_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"checkout_return_path": "/apps"
}
'import requests
url = "https://app.base44.com/api/billing/create-checkout-session/{price_id}"
payload = { "checkout_return_path": "/apps" }
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({checkout_return_path: '/apps'})
};
fetch('https://app.base44.com/api/billing/create-checkout-session/{price_id}', 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/billing/create-checkout-session/{price_id}",
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([
'checkout_return_path' => '/apps'
]),
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/billing/create-checkout-session/{price_id}"
payload := strings.NewReader("{\n \"checkout_return_path\": \"/apps\"\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/billing/create-checkout-session/{price_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"checkout_return_path\": \"/apps\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/billing/create-checkout-session/{price_id}")
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 \"checkout_return_path\": \"/apps\"\n}"
response = http.request(request)
puts response.read_body{
"session_id": "cs_live_a1B2c3D4e5F6g7H8i9J0",
"url": "https://checkout.stripe.com/c/pay/cs_live_a1B2c3D4e5F6g7H8i9J0"
}{
"detail": [
{
"type": "string_too_long",
"loc": [
"body",
"checkout_return_path"
],
"msg": "String should have at most 2048 characters",
"input": "/apps?ref=...",
"ctx": {
"max_length": 2048
}
}
]
}Create plan checkout
Creates a checkout page where the payer buys a paid plan for your workspace. Nothing is charged until they pay on that page.
Pass the price ID of the plan, from price_ids in List plans, then open url in a browser and let the payer complete the purchase. The page is on Stripe or Wix, depending on how the workspace is billed. Only the workspace owner can start a checkout.
If the workspace already pays for a plan, move it with Change plan or Change Wix plan instead. Checkout refuses it with 409 when the plan is billed through Stripe and 400 when it’s billed through Wix. A workspace billed through the App Store, Google Play or an external contract can’t check out here either.
Set checkout_return_path to send the payer back to a page on Base44 after checkout. Without it, they land on the billing page.
Each call creates a new checkout page, including a retry after a lost response. Send the payer only one.
The base rate limit is 8 requests per hour per user. See Rate limits for the multiplier your plan gets.
checkout_return_path in the body. Other request fields aren’t supported and their behavior can change.curl --request POST \
--url https://app.base44.com/api/billing/create-checkout-session/{price_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"checkout_return_path": "/apps"
}
'import requests
url = "https://app.base44.com/api/billing/create-checkout-session/{price_id}"
payload = { "checkout_return_path": "/apps" }
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({checkout_return_path: '/apps'})
};
fetch('https://app.base44.com/api/billing/create-checkout-session/{price_id}', 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/billing/create-checkout-session/{price_id}",
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([
'checkout_return_path' => '/apps'
]),
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/billing/create-checkout-session/{price_id}"
payload := strings.NewReader("{\n \"checkout_return_path\": \"/apps\"\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/billing/create-checkout-session/{price_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"checkout_return_path\": \"/apps\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/billing/create-checkout-session/{price_id}")
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 \"checkout_return_path\": \"/apps\"\n}"
response = http.request(request)
puts response.read_body{
"session_id": "cs_live_a1B2c3D4e5F6g7H8i9J0",
"url": "https://checkout.stripe.com/c/pay/cs_live_a1B2c3D4e5F6g7H8i9J0"
}{
"detail": [
{
"type": "string_too_long",
"loc": [
"body",
"checkout_return_path"
],
"msg": "String should have at most 2048 characters",
"input": "/apps?ref=...",
"ctx": {
"max_length": 2048
}
}
]
}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
Price ID of the plan to buy, from price_ids in List plans.
Body
Request model for checkout session creation.
Path on Base44 to send the payer back to after checkout, such as /apps. It must start with a single /. Any other value is ignored, and the payer lands on the billing page.
2048"/apps"
Response
The checkout page to send the payer to.
A checkout for a plan.
ID of the Stripe Checkout session. An empty string when the workspace checks out through Wix.
"cs_live_a1B2c3D4e5F6g7H8i9J0"
Checkout page for this purchase. Open it in a browser so the payer can review and pay. On Wix the link itself opens the checkout, so don't log or share it.
"https://checkout.stripe.com/c/pay/cs_live_a1B2c3D4e5F6g7H8i9J0"
Was this page helpful?