Start a plan checkout session
curl --request POST \
--url https://api.orbit.devotel.io/api/v1/billing/checkout \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"planId": "scale_monthly",
"successUrl": "https://orbit.devotel.io/billing?checkout=success",
"cancelUrl": "https://orbit.devotel.io/billing?checkout=cancelled"
}
'import requests
url = "https://api.orbit.devotel.io/api/v1/billing/checkout"
payload = {
"planId": "scale_monthly",
"successUrl": "https://orbit.devotel.io/billing?checkout=success",
"cancelUrl": "https://orbit.devotel.io/billing?checkout=cancelled"
}
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({
planId: 'scale_monthly',
successUrl: 'https://orbit.devotel.io/billing?checkout=success',
cancelUrl: 'https://orbit.devotel.io/billing?checkout=cancelled'
})
};
fetch('https://api.orbit.devotel.io/api/v1/billing/checkout', 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://api.orbit.devotel.io/api/v1/billing/checkout",
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([
'planId' => 'scale_monthly',
'successUrl' => 'https://orbit.devotel.io/billing?checkout=success',
'cancelUrl' => 'https://orbit.devotel.io/billing?checkout=cancelled'
]),
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://api.orbit.devotel.io/api/v1/billing/checkout"
payload := strings.NewReader("{\n \"planId\": \"scale_monthly\",\n \"successUrl\": \"https://orbit.devotel.io/billing?checkout=success\",\n \"cancelUrl\": \"https://orbit.devotel.io/billing?checkout=cancelled\"\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://api.orbit.devotel.io/api/v1/billing/checkout")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"planId\": \"scale_monthly\",\n \"successUrl\": \"https://orbit.devotel.io/billing?checkout=success\",\n \"cancelUrl\": \"https://orbit.devotel.io/billing?checkout=cancelled\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.orbit.devotel.io/api/v1/billing/checkout")
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 \"planId\": \"scale_monthly\",\n \"successUrl\": \"https://orbit.devotel.io/billing?checkout=success\",\n \"cancelUrl\": \"https://orbit.devotel.io/billing?checkout=cancelled\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"checkoutUrl": "https://checkout.stripe.com/c/pay/cs_test_a1b2c3"
},
"meta": {
"request_id": "req_01H8XGJ",
"timestamp": "2026-08-02T12:00:00.000Z"
}
}Billing
Start a plan checkout session
Creates a Stripe Checkout session for a subscription plan upgrade and returns the hosted checkoutUrl to redirect the customer to. Pass the target planId (or an explicit priceId) plus trusted successUrl and cancelUrl redirect targets. Requests are idempotent for 60 seconds per organization and plan, so a double-click returns the same session URL.
POST
/
api
/
v1
/
billing
/
checkout
Start a plan checkout session
curl --request POST \
--url https://api.orbit.devotel.io/api/v1/billing/checkout \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"planId": "scale_monthly",
"successUrl": "https://orbit.devotel.io/billing?checkout=success",
"cancelUrl": "https://orbit.devotel.io/billing?checkout=cancelled"
}
'import requests
url = "https://api.orbit.devotel.io/api/v1/billing/checkout"
payload = {
"planId": "scale_monthly",
"successUrl": "https://orbit.devotel.io/billing?checkout=success",
"cancelUrl": "https://orbit.devotel.io/billing?checkout=cancelled"
}
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({
planId: 'scale_monthly',
successUrl: 'https://orbit.devotel.io/billing?checkout=success',
cancelUrl: 'https://orbit.devotel.io/billing?checkout=cancelled'
})
};
fetch('https://api.orbit.devotel.io/api/v1/billing/checkout', 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://api.orbit.devotel.io/api/v1/billing/checkout",
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([
'planId' => 'scale_monthly',
'successUrl' => 'https://orbit.devotel.io/billing?checkout=success',
'cancelUrl' => 'https://orbit.devotel.io/billing?checkout=cancelled'
]),
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://api.orbit.devotel.io/api/v1/billing/checkout"
payload := strings.NewReader("{\n \"planId\": \"scale_monthly\",\n \"successUrl\": \"https://orbit.devotel.io/billing?checkout=success\",\n \"cancelUrl\": \"https://orbit.devotel.io/billing?checkout=cancelled\"\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://api.orbit.devotel.io/api/v1/billing/checkout")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"planId\": \"scale_monthly\",\n \"successUrl\": \"https://orbit.devotel.io/billing?checkout=success\",\n \"cancelUrl\": \"https://orbit.devotel.io/billing?checkout=cancelled\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.orbit.devotel.io/api/v1/billing/checkout")
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 \"planId\": \"scale_monthly\",\n \"successUrl\": \"https://orbit.devotel.io/billing?checkout=success\",\n \"cancelUrl\": \"https://orbit.devotel.io/billing?checkout=cancelled\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"checkoutUrl": "https://checkout.stripe.com/c/pay/cs_test_a1b2c3"
},
"meta": {
"request_id": "req_01H8XGJ",
"timestamp": "2026-08-02T12:00:00.000Z"
}
}Authorizations
BearerApiKey
Dashboard JWT token from Clerk
Body
application/json
Identifier of the plan the customer is upgrading to.
Minimum string length:
1Trusted Orbit URL to redirect to after successful payment.
Trusted Orbit URL to redirect to if the customer cancels.
Optional explicit Stripe price id; derived from planId when omitted.
Minimum string length:
1⌘I