Create Checkout Session
curl --request POST \
--url https://api.nozle.app/api/v1/checkout \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customer_id": "<string>",
"plan_code": "<string>",
"return_url": "<string>",
"success_url": "<string>"
}
'import requests
url = "https://api.nozle.app/api/v1/checkout"
payload = {
"customer_id": "<string>",
"plan_code": "<string>",
"return_url": "<string>",
"success_url": "<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({
customer_id: '<string>',
plan_code: '<string>',
return_url: '<string>',
success_url: '<string>'
})
};
fetch('https://api.nozle.app/api/v1/checkout', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.nozle.app/api/v1/checkout"
payload := strings.NewReader("{\n \"customer_id\": \"<string>\",\n \"plan_code\": \"<string>\",\n \"return_url\": \"<string>\",\n \"success_url\": \"<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))
}require 'uri'
require 'net/http'
url = URI("https://api.nozle.app/api/v1/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 \"customer_id\": \"<string>\",\n \"plan_code\": \"<string>\",\n \"return_url\": \"<string>\",\n \"success_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.nozle.app/api/v1/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([
'customer_id' => '<string>',
'plan_code' => '<string>',
'return_url' => '<string>',
'success_url' => '<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;
}HttpResponse<String> response = Unirest.post("https://api.nozle.app/api/v1/checkout")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customer_id\": \"<string>\",\n \"plan_code\": \"<string>\",\n \"return_url\": \"<string>\",\n \"success_url\": \"<string>\"\n}")
.asString();{
"type": "<string>",
"client_secret": "<string>",
"url": "<string>",
"clientSecret": "<string>",
"invoice_id": "<string>",
"amount_cents": 123,
"currency": "<string>"
}Checkout & Subscriptions
Create Checkout Session
POST
/
checkout
Create Checkout Session
curl --request POST \
--url https://api.nozle.app/api/v1/checkout \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customer_id": "<string>",
"plan_code": "<string>",
"return_url": "<string>",
"success_url": "<string>"
}
'import requests
url = "https://api.nozle.app/api/v1/checkout"
payload = {
"customer_id": "<string>",
"plan_code": "<string>",
"return_url": "<string>",
"success_url": "<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({
customer_id: '<string>',
plan_code: '<string>',
return_url: '<string>',
success_url: '<string>'
})
};
fetch('https://api.nozle.app/api/v1/checkout', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.nozle.app/api/v1/checkout"
payload := strings.NewReader("{\n \"customer_id\": \"<string>\",\n \"plan_code\": \"<string>\",\n \"return_url\": \"<string>\",\n \"success_url\": \"<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))
}require 'uri'
require 'net/http'
url = URI("https://api.nozle.app/api/v1/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 \"customer_id\": \"<string>\",\n \"plan_code\": \"<string>\",\n \"return_url\": \"<string>\",\n \"success_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.nozle.app/api/v1/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([
'customer_id' => '<string>',
'plan_code' => '<string>',
'return_url' => '<string>',
'success_url' => '<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;
}HttpResponse<String> response = Unirest.post("https://api.nozle.app/api/v1/checkout")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customer_id\": \"<string>\",\n \"plan_code\": \"<string>\",\n \"return_url\": \"<string>\",\n \"success_url\": \"<string>\"\n}")
.asString();{
"type": "<string>",
"client_secret": "<string>",
"url": "<string>",
"clientSecret": "<string>",
"invoice_id": "<string>",
"amount_cents": 123,
"currency": "<string>"
}Create a payment-gated plan checkout from a trusted merchant backend.
Auth: secret key only. Publishable keys are always rejected.
Plan checkout is payment-gated. Free-to-paid checkout uses an incomplete subscription. Paid-to-paid upgrades keep the old subscription active in a durable pending intent and apply the billing change only after Stripe confirms payment.
If prepaid credits fully cover a paid plan change, Nozle applies it without Stripe and returns
Checkout relies on these Stripe events:
The merchant backend derives
customer_id from its authenticated user or team. Do not trust a browser-provided customer ID. The response contains a hosted URL or Stripe Checkout client_secret, or reports an immediately completed or scheduled transition.Modes
Plan checkout
Use this when a customer is selecting a plan.string
required
External customer ID. The customer must already exist.
string
required
The plan code to subscribe the customer to (e.g.
pro).type: "completed". Free plans may also complete immediately. A downgrade or other cycle-end transition returns type: "scheduled"; browser callers still use this same endpoint.
Return URL
string
URL Stripe should return to after embedded checkout completes. It must use an exactly allowlisted HTTPS origin. If omitted, Nozle uses the configured dashboard return URL.
string
Backward-compatible alias for
return_url.Request examples
Plan checkout:{
"customer_id": "customer_123",
"plan_code": "growth",
"return_url": "https://app.example.com/settings/billing"
}
Response
string
required
stripe, completed, or scheduled.string
Stripe Checkout Session client secret. Pass this to
stripe.initEmbeddedCheckout().string
Hosted checkout URL. Navigate the current page to this URL.
string
Camel-case alias for
client_secret.string
Nozle invoice ID being paid.
integer
Amount due for the checkout session, in the invoice currency’s smallest unit.
string
Invoice currency.
Credit-funded response
When no external payment remains due:{
"type": "completed",
"status": "succeeded",
"payment_source": "credits",
"subscription_id": "subscription_uuid",
"plan_code": "pro",
"invoice_id": "invoice_uuid",
"amount_cents": 0,
"currency": "USD"
}
Scheduled response
{
"type": "scheduled",
"status": "pending",
"subscription_id": "subscription_uuid",
"plan_code": "starter"
}
Webhook requirement
Stripe must be able to reach your Nozle public API URL. When a Stripe provider is connected, Nozle registers the Stripe webhook endpoint for that tenant’s Stripe account:{NOZLE_PUBLIC_API_URL}/webhooks/stripe/{organization_id}?code={stripe_provider_code}
payment_intent.succeededpayment_intent.payment_failedpayment_intent.canceled