curl --request POST \
--url https://api.orbit.devotel.io/api/v1/billing/checkout \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"planId": "<string>",
"successUrl": "<string>",
"cancelUrl": "<string>",
"priceId": "<string>"
}
'import requests
url = "https://api.orbit.devotel.io/api/v1/billing/checkout"
payload = {
"planId": "<string>",
"successUrl": "<string>",
"cancelUrl": "<string>",
"priceId": "<string>"
}
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: '<string>',
successUrl: '<string>',
cancelUrl: '<string>',
priceId: '<string>'
})
};
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' => '<string>',
'successUrl' => '<string>',
'cancelUrl' => '<string>',
'priceId' => '<string>'
]),
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\": \"<string>\",\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"priceId\": \"<string>\"\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\": \"<string>\",\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"priceId\": \"<string>\"\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\": \"<string>\",\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"priceId\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "<string>",
"status": 429,
"retry_after": 2
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}Create a plan checkout session
Creates a hosted checkout session for a plan subscription (the Stripe page the customer is redirected to) and returns its URL. Rapid retries with the same plan are deduplicated for 60 seconds, so repeat clicks return the same session. Owner, admin, or billing role required; rate-limited as a money-moving operation. Use it when starting or upgrading a plan subscription — redirect the browser to the returned URL.
curl --request POST \
--url https://api.orbit.devotel.io/api/v1/billing/checkout \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"planId": "<string>",
"successUrl": "<string>",
"cancelUrl": "<string>",
"priceId": "<string>"
}
'import requests
url = "https://api.orbit.devotel.io/api/v1/billing/checkout"
payload = {
"planId": "<string>",
"successUrl": "<string>",
"cancelUrl": "<string>",
"priceId": "<string>"
}
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: '<string>',
successUrl: '<string>',
cancelUrl: '<string>',
priceId: '<string>'
})
};
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' => '<string>',
'successUrl' => '<string>',
'cancelUrl' => '<string>',
'priceId' => '<string>'
]),
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\": \"<string>\",\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"priceId\": \"<string>\"\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\": \"<string>\",\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"priceId\": \"<string>\"\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\": \"<string>\",\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"priceId\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "<string>",
"status": 429,
"retry_after": 2
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}Authorizations
Dashboard JWT token from Clerk
Headers
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the Idempotency-Replay: true response header.
1 - 255Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.
true, false Body
Plan to subscribe to (an id from GET /billing/plans).
1URL the provider redirects to on a completed checkout (e.g. https://orbit.devotel.io/billing?checkout=success). Must use a trusted Orbit origin (orbit.devotel.io).
URL the provider redirects to when the customer abandons checkout (e.g. https://orbit.devotel.io/billing?checkout=cancelled). Must use a trusted Orbit origin (orbit.devotel.io).
Optional billing-provider price override; resolved from planId when omitted.
1Response
The hosted checkout session — checkoutUrl (the provider URL to redirect the browser to) — in the standard { data, meta } envelope.
The hosted checkout session — checkoutUrl (the provider URL to redirect the browser to) — in the standard { data, meta } envelope.