curl --request POST \
--url https://api.beta.suby.fi/v3/checkout/sessions \
--header 'Content-Type: application/json' \
--header 'X-Suby-Api-Key: <api-key>' \
--data '
{
"successUrl": "<string>",
"cancelUrl": "<string>",
"productId": "pro_abc123",
"lineItems": [
{
"productId": "pro_abc123",
"quantity": 1,
"adjustable": true,
"min": 499,
"max": 500
}
],
"amount": 2,
"currency": "<string>",
"displayName": "<string>",
"customerId": "cus_abc123",
"customerData": {
"email": "jsmith@example.com",
"firstName": "<string>",
"lastName": "<string>"
},
"discountCode": "<string>",
"metadata": {},
"customFields": [
{
"key": "<string>",
"label": "<string>",
"required": true,
"placeholder": "<string>",
"options": [
{
"value": "<string>",
"label": "<string>"
}
],
"validation": {
"regex": "<string>",
"errorMessage": "<string>"
},
"defaultValue": "<string>"
}
],
"expiresIn": 302430
}
'import requests
url = "https://api.beta.suby.fi/v3/checkout/sessions"
payload = {
"successUrl": "<string>",
"cancelUrl": "<string>",
"productId": "pro_abc123",
"lineItems": [
{
"productId": "pro_abc123",
"quantity": 1,
"adjustable": True,
"min": 499,
"max": 500
}
],
"amount": 2,
"currency": "<string>",
"displayName": "<string>",
"customerId": "cus_abc123",
"customerData": {
"email": "jsmith@example.com",
"firstName": "<string>",
"lastName": "<string>"
},
"discountCode": "<string>",
"metadata": {},
"customFields": [
{
"key": "<string>",
"label": "<string>",
"required": True,
"placeholder": "<string>",
"options": [
{
"value": "<string>",
"label": "<string>"
}
],
"validation": {
"regex": "<string>",
"errorMessage": "<string>"
},
"defaultValue": "<string>"
}
],
"expiresIn": 302430
}
headers = {
"X-Suby-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Suby-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
successUrl: '<string>',
cancelUrl: '<string>',
productId: 'pro_abc123',
lineItems: [{productId: 'pro_abc123', quantity: 1, adjustable: true, min: 499, max: 500}],
amount: 2,
currency: '<string>',
displayName: '<string>',
customerId: 'cus_abc123',
customerData: {email: 'jsmith@example.com', firstName: '<string>', lastName: '<string>'},
discountCode: '<string>',
metadata: {},
customFields: [
{
key: '<string>',
label: '<string>',
required: true,
placeholder: '<string>',
options: [{value: '<string>', label: '<string>'}],
validation: {regex: '<string>', errorMessage: '<string>'},
defaultValue: '<string>'
}
],
expiresIn: 302430
})
};
fetch('https://api.beta.suby.fi/v3/checkout/sessions', 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.beta.suby.fi/v3/checkout/sessions",
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([
'successUrl' => '<string>',
'cancelUrl' => '<string>',
'productId' => 'pro_abc123',
'lineItems' => [
[
'productId' => 'pro_abc123',
'quantity' => 1,
'adjustable' => true,
'min' => 499,
'max' => 500
]
],
'amount' => 2,
'currency' => '<string>',
'displayName' => '<string>',
'customerId' => 'cus_abc123',
'customerData' => [
'email' => 'jsmith@example.com',
'firstName' => '<string>',
'lastName' => '<string>'
],
'discountCode' => '<string>',
'metadata' => [
],
'customFields' => [
[
'key' => '<string>',
'label' => '<string>',
'required' => true,
'placeholder' => '<string>',
'options' => [
[
'value' => '<string>',
'label' => '<string>'
]
],
'validation' => [
'regex' => '<string>',
'errorMessage' => '<string>'
],
'defaultValue' => '<string>'
]
],
'expiresIn' => 302430
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Suby-Api-Key: <api-key>"
],
]);
$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.beta.suby.fi/v3/checkout/sessions"
payload := strings.NewReader("{\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"productId\": \"pro_abc123\",\n \"lineItems\": [\n {\n \"productId\": \"pro_abc123\",\n \"quantity\": 1,\n \"adjustable\": true,\n \"min\": 499,\n \"max\": 500\n }\n ],\n \"amount\": 2,\n \"currency\": \"<string>\",\n \"displayName\": \"<string>\",\n \"customerId\": \"cus_abc123\",\n \"customerData\": {\n \"email\": \"jsmith@example.com\",\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\"\n },\n \"discountCode\": \"<string>\",\n \"metadata\": {},\n \"customFields\": [\n {\n \"key\": \"<string>\",\n \"label\": \"<string>\",\n \"required\": true,\n \"placeholder\": \"<string>\",\n \"options\": [\n {\n \"value\": \"<string>\",\n \"label\": \"<string>\"\n }\n ],\n \"validation\": {\n \"regex\": \"<string>\",\n \"errorMessage\": \"<string>\"\n },\n \"defaultValue\": \"<string>\"\n }\n ],\n \"expiresIn\": 302430\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Suby-Api-Key", "<api-key>")
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.beta.suby.fi/v3/checkout/sessions")
.header("X-Suby-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"productId\": \"pro_abc123\",\n \"lineItems\": [\n {\n \"productId\": \"pro_abc123\",\n \"quantity\": 1,\n \"adjustable\": true,\n \"min\": 499,\n \"max\": 500\n }\n ],\n \"amount\": 2,\n \"currency\": \"<string>\",\n \"displayName\": \"<string>\",\n \"customerId\": \"cus_abc123\",\n \"customerData\": {\n \"email\": \"jsmith@example.com\",\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\"\n },\n \"discountCode\": \"<string>\",\n \"metadata\": {},\n \"customFields\": [\n {\n \"key\": \"<string>\",\n \"label\": \"<string>\",\n \"required\": true,\n \"placeholder\": \"<string>\",\n \"options\": [\n {\n \"value\": \"<string>\",\n \"label\": \"<string>\"\n }\n ],\n \"validation\": {\n \"regex\": \"<string>\",\n \"errorMessage\": \"<string>\"\n },\n \"defaultValue\": \"<string>\"\n }\n ],\n \"expiresIn\": 302430\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.beta.suby.fi/v3/checkout/sessions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Suby-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"productId\": \"pro_abc123\",\n \"lineItems\": [\n {\n \"productId\": \"pro_abc123\",\n \"quantity\": 1,\n \"adjustable\": true,\n \"min\": 499,\n \"max\": 500\n }\n ],\n \"amount\": 2,\n \"currency\": \"<string>\",\n \"displayName\": \"<string>\",\n \"customerId\": \"cus_abc123\",\n \"customerData\": {\n \"email\": \"jsmith@example.com\",\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\"\n },\n \"discountCode\": \"<string>\",\n \"metadata\": {},\n \"customFields\": [\n {\n \"key\": \"<string>\",\n \"label\": \"<string>\",\n \"required\": true,\n \"placeholder\": \"<string>\",\n \"options\": [\n {\n \"value\": \"<string>\",\n \"label\": \"<string>\"\n }\n ],\n \"validation\": {\n \"regex\": \"<string>\",\n \"errorMessage\": \"<string>\"\n },\n \"defaultValue\": \"<string>\"\n }\n ],\n \"expiresIn\": 302430\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "cs_abc123",
"organizationId": "<string>",
"productId": "<string>",
"lineItems": [
{
"productId": "<string>",
"quantity": 123,
"adjustable": true,
"min": 123,
"max": 123
}
],
"amount": 123,
"currency": "<string>",
"displayName": "<string>",
"allowPromo": true,
"customerId": "<string>",
"customerEmail": "<string>",
"customerFirstName": "<string>",
"customerLastName": "<string>",
"successUrl": "<string>",
"cancelUrl": "<string>",
"discountCode": "<string>",
"metadata": {},
"customFields": [
{
"key": "<string>",
"label": "<string>",
"required": true,
"placeholder": "<string>",
"options": [
{
"value": "<string>",
"label": "<string>"
}
],
"validation": {
"regex": "<string>",
"errorMessage": "<string>"
},
"defaultValue": "<string>"
}
],
"url": "<string>",
"expiresAt": 123,
"createdAt": 123
},
"message": "<string>"
}{
"success": false,
"error": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Validation failed",
"data": {
"fieldErrors": [
{
"field": "method",
"message": "method is a required field"
}
]
}
}Create a checkout session
Mint a signed hosted-checkout token (cs_…). Provide a productId,
lineItems, or amount+currency. mode=subscription requires a
recurring productId. The returned url is the hosted checkout page.
curl --request POST \
--url https://api.beta.suby.fi/v3/checkout/sessions \
--header 'Content-Type: application/json' \
--header 'X-Suby-Api-Key: <api-key>' \
--data '
{
"successUrl": "<string>",
"cancelUrl": "<string>",
"productId": "pro_abc123",
"lineItems": [
{
"productId": "pro_abc123",
"quantity": 1,
"adjustable": true,
"min": 499,
"max": 500
}
],
"amount": 2,
"currency": "<string>",
"displayName": "<string>",
"customerId": "cus_abc123",
"customerData": {
"email": "jsmith@example.com",
"firstName": "<string>",
"lastName": "<string>"
},
"discountCode": "<string>",
"metadata": {},
"customFields": [
{
"key": "<string>",
"label": "<string>",
"required": true,
"placeholder": "<string>",
"options": [
{
"value": "<string>",
"label": "<string>"
}
],
"validation": {
"regex": "<string>",
"errorMessage": "<string>"
},
"defaultValue": "<string>"
}
],
"expiresIn": 302430
}
'import requests
url = "https://api.beta.suby.fi/v3/checkout/sessions"
payload = {
"successUrl": "<string>",
"cancelUrl": "<string>",
"productId": "pro_abc123",
"lineItems": [
{
"productId": "pro_abc123",
"quantity": 1,
"adjustable": True,
"min": 499,
"max": 500
}
],
"amount": 2,
"currency": "<string>",
"displayName": "<string>",
"customerId": "cus_abc123",
"customerData": {
"email": "jsmith@example.com",
"firstName": "<string>",
"lastName": "<string>"
},
"discountCode": "<string>",
"metadata": {},
"customFields": [
{
"key": "<string>",
"label": "<string>",
"required": True,
"placeholder": "<string>",
"options": [
{
"value": "<string>",
"label": "<string>"
}
],
"validation": {
"regex": "<string>",
"errorMessage": "<string>"
},
"defaultValue": "<string>"
}
],
"expiresIn": 302430
}
headers = {
"X-Suby-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Suby-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
successUrl: '<string>',
cancelUrl: '<string>',
productId: 'pro_abc123',
lineItems: [{productId: 'pro_abc123', quantity: 1, adjustable: true, min: 499, max: 500}],
amount: 2,
currency: '<string>',
displayName: '<string>',
customerId: 'cus_abc123',
customerData: {email: 'jsmith@example.com', firstName: '<string>', lastName: '<string>'},
discountCode: '<string>',
metadata: {},
customFields: [
{
key: '<string>',
label: '<string>',
required: true,
placeholder: '<string>',
options: [{value: '<string>', label: '<string>'}],
validation: {regex: '<string>', errorMessage: '<string>'},
defaultValue: '<string>'
}
],
expiresIn: 302430
})
};
fetch('https://api.beta.suby.fi/v3/checkout/sessions', 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.beta.suby.fi/v3/checkout/sessions",
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([
'successUrl' => '<string>',
'cancelUrl' => '<string>',
'productId' => 'pro_abc123',
'lineItems' => [
[
'productId' => 'pro_abc123',
'quantity' => 1,
'adjustable' => true,
'min' => 499,
'max' => 500
]
],
'amount' => 2,
'currency' => '<string>',
'displayName' => '<string>',
'customerId' => 'cus_abc123',
'customerData' => [
'email' => 'jsmith@example.com',
'firstName' => '<string>',
'lastName' => '<string>'
],
'discountCode' => '<string>',
'metadata' => [
],
'customFields' => [
[
'key' => '<string>',
'label' => '<string>',
'required' => true,
'placeholder' => '<string>',
'options' => [
[
'value' => '<string>',
'label' => '<string>'
]
],
'validation' => [
'regex' => '<string>',
'errorMessage' => '<string>'
],
'defaultValue' => '<string>'
]
],
'expiresIn' => 302430
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Suby-Api-Key: <api-key>"
],
]);
$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.beta.suby.fi/v3/checkout/sessions"
payload := strings.NewReader("{\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"productId\": \"pro_abc123\",\n \"lineItems\": [\n {\n \"productId\": \"pro_abc123\",\n \"quantity\": 1,\n \"adjustable\": true,\n \"min\": 499,\n \"max\": 500\n }\n ],\n \"amount\": 2,\n \"currency\": \"<string>\",\n \"displayName\": \"<string>\",\n \"customerId\": \"cus_abc123\",\n \"customerData\": {\n \"email\": \"jsmith@example.com\",\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\"\n },\n \"discountCode\": \"<string>\",\n \"metadata\": {},\n \"customFields\": [\n {\n \"key\": \"<string>\",\n \"label\": \"<string>\",\n \"required\": true,\n \"placeholder\": \"<string>\",\n \"options\": [\n {\n \"value\": \"<string>\",\n \"label\": \"<string>\"\n }\n ],\n \"validation\": {\n \"regex\": \"<string>\",\n \"errorMessage\": \"<string>\"\n },\n \"defaultValue\": \"<string>\"\n }\n ],\n \"expiresIn\": 302430\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Suby-Api-Key", "<api-key>")
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.beta.suby.fi/v3/checkout/sessions")
.header("X-Suby-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"productId\": \"pro_abc123\",\n \"lineItems\": [\n {\n \"productId\": \"pro_abc123\",\n \"quantity\": 1,\n \"adjustable\": true,\n \"min\": 499,\n \"max\": 500\n }\n ],\n \"amount\": 2,\n \"currency\": \"<string>\",\n \"displayName\": \"<string>\",\n \"customerId\": \"cus_abc123\",\n \"customerData\": {\n \"email\": \"jsmith@example.com\",\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\"\n },\n \"discountCode\": \"<string>\",\n \"metadata\": {},\n \"customFields\": [\n {\n \"key\": \"<string>\",\n \"label\": \"<string>\",\n \"required\": true,\n \"placeholder\": \"<string>\",\n \"options\": [\n {\n \"value\": \"<string>\",\n \"label\": \"<string>\"\n }\n ],\n \"validation\": {\n \"regex\": \"<string>\",\n \"errorMessage\": \"<string>\"\n },\n \"defaultValue\": \"<string>\"\n }\n ],\n \"expiresIn\": 302430\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.beta.suby.fi/v3/checkout/sessions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Suby-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"successUrl\": \"<string>\",\n \"cancelUrl\": \"<string>\",\n \"productId\": \"pro_abc123\",\n \"lineItems\": [\n {\n \"productId\": \"pro_abc123\",\n \"quantity\": 1,\n \"adjustable\": true,\n \"min\": 499,\n \"max\": 500\n }\n ],\n \"amount\": 2,\n \"currency\": \"<string>\",\n \"displayName\": \"<string>\",\n \"customerId\": \"cus_abc123\",\n \"customerData\": {\n \"email\": \"jsmith@example.com\",\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\"\n },\n \"discountCode\": \"<string>\",\n \"metadata\": {},\n \"customFields\": [\n {\n \"key\": \"<string>\",\n \"label\": \"<string>\",\n \"required\": true,\n \"placeholder\": \"<string>\",\n \"options\": [\n {\n \"value\": \"<string>\",\n \"label\": \"<string>\"\n }\n ],\n \"validation\": {\n \"regex\": \"<string>\",\n \"errorMessage\": \"<string>\"\n },\n \"defaultValue\": \"<string>\"\n }\n ],\n \"expiresIn\": 302430\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "cs_abc123",
"organizationId": "<string>",
"productId": "<string>",
"lineItems": [
{
"productId": "<string>",
"quantity": 123,
"adjustable": true,
"min": 123,
"max": 123
}
],
"amount": 123,
"currency": "<string>",
"displayName": "<string>",
"allowPromo": true,
"customerId": "<string>",
"customerEmail": "<string>",
"customerFirstName": "<string>",
"customerLastName": "<string>",
"successUrl": "<string>",
"cancelUrl": "<string>",
"discountCode": "<string>",
"metadata": {},
"customFields": [
{
"key": "<string>",
"label": "<string>",
"required": true,
"placeholder": "<string>",
"options": [
{
"value": "<string>",
"label": "<string>"
}
],
"validation": {
"regex": "<string>",
"errorMessage": "<string>"
},
"defaultValue": "<string>"
}
],
"url": "<string>",
"expiresAt": 123,
"createdAt": 123
},
"message": "<string>"
}{
"success": false,
"error": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Validation failed",
"data": {
"fieldErrors": [
{
"field": "method",
"message": "method is a required field"
}
]
}
}Authorizations
Secret API key. sk_live_… (production) or sk_sandbox_… (sandbox).
Headers
Optional key (≤255 chars, e.g. a UUID v4) that makes this POST safe to retry: the first request executes and its response is cached for 24h; a retry with the SAME key replays that response instead of re-executing (no duplicate payment/subscription). A reused key with a different request → 422 IDEMPOTENCY_KEY_CONFLICT; a retry while the first is still in flight → 409. See the Idempotency guide.
255"5f3b9c2e-1a4d-4f2b-9c31-7e2a1b6d8c04"
Body
Exactly ONE pricing intent is required: productId (single product), lineItems (a bundle of products), or amount + currency (ad-hoc, no product). mode=subscription requires a recurring productId (bundles/ad-hoc are one-time only).
payment = one-shot; subscription = recurring (requires a recurring productId).
payment, subscription Redirect after a successful payment. Required.
Redirect if the payer cancels. Required.
Pricing intent A: a single product. Mutually exclusive with lineItems / amount.
"pro_abc123"
Pricing intent B: 1–20 product lines charged as one Payment (a bundle). Mutually exclusive with productId / amount.
1 - 20 elementsShow child attributes
Show child attributes
Pricing intent C: ad-hoc amount in cents (no product). Requires currency. Mutually exclusive with productId / lineItems.
x >= 1ISO 4217. Required with amount.
^[A-Z]{3}$Label on the hosted page + Payment snapshot. Ad-hoc sessions only; product-backed sessions use the product name.
200MoR VAT: exclusive (default) adds VAT on top → the hosted page shows the TTC; inclusive treats the price as VAT-inclusive. Signed into the session.
inclusive, exclusive Bind the session to an existing customer. Mutually exclusive with customerData.
"cus_abc123"
Prefill hints for the hosted page (all optional, editable by the payer). Use instead of customerId for a new buyer. Same shape as on payments, but email is optional here.
Show child attributes
Show child attributes
Pre-apply a promo code (re-validated server-side).
40Key-value pairs. ≤50 keys, keys ≤40 chars, values are
strings ≤500 chars (or null to clear). Nested structures must be
JSON-stringified into a single string value.
Show child attributes
Show child attributes
Extra fields collected on the hosted checkout page (max 10).
10Show child attributes
Show child attributes
Session TTL in seconds (default 24h, max 7d).
60 <= x <= 604800Was this page helpful?

