Create Hosted Checkout
This section guides you on how to create a Checkout Session via API on the server side and redirect the user to GStable's secure hosted cashier.
A Checkout Session is a one-time payment session where we handle cross-chain routing and asset settlement under the hood, and funds are settled directly to your non-custodial wallet.
1. Prerequisites
Before calling the interface, please ensure you have the following information ready:
- API Endpoint:
https://api.gstable.io/payment/v1/session/checkout/create - API Key: Your merchant key for authentication.
- Account ID: Your collection account ID (e.g.,
acc_...), determining the target wallet for fund settlement. - Settlement Token: The settlement asset identifier you wish to receive (e.g.,
polygon::usdc).
2. Build API Request
The core of a Checkout Session is the lineItems parameter. You can reference created inventory products or directly define one-time products (ad-hoc construction).
Amount Precision Note (Micro-USD)
To ensure high precision for crypto payments, all amount fields (unitPrice) use Micro-USD (millionth of a US Dollar) as the unit and must be integers.
- 1 USD = 1,000,000 Micro-USD
- Example: Product price is $19.90, pass 19,900,000 in API.
Request Parameter Example (JSON)
The following example shows how to create a payment session containing a one-time item:
{
"accountId": "acc_example_merchant_02",
"settlementToken": "polygon::usdc",
"successUrl": "https://your-site.com/success?orderId=ORD_001",
"payerEmailRequired": 1,
"feeModel": 1,
"lineItems": [
{
"itemType": "one_time",
"quantity": 1,
"unitPrice": 19900000,
"productData": {
"productName": "Premium Subscription (1 Month)",
"productDescription": "Unlock all premium features",
"imageUrl": "https://your-site.com/img/premium.png"
}
}
],
"metadata": {
"orderId": "ORD_001",
"userId": "u_123"
}
}
unitPrice:19900000corresponds to $19.90 USD.itemType:one_timemeans no need to pre-create a product ID.feeModel:1represents merchant bears the fee.
3. Code Implementation
Choose your backend programming language, copy the code below, and run it on your server.
- Node.js
- Python
- PHP
- Go
- Java
// Use native fetch (Node.js 18+) or node-fetch
const createSession = async () => {
const response = await fetch('https://api.gstable.io/payment/v1/session/checkout/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer <YOUR_API_KEY>' // Replace with your API Key
},
body: JSON.stringify({
accountId: 'acc_example_12345678',
settlementToken: 'polygon::usdc', // Currency you wish to receive, must be enabled in the account ID
successUrl: 'https://your-site.com/success',
payerEmailRequired: 1, // Require user to fill in email
lineItems: [
{
itemType: 'one_time',
quantity: 1,
unitPrice: 20000000, // $20.00 USD
productData: {
productName: 'T-Shirt Dark Mode',
imageUrl: 'https://example.com/t-shirt.png'
}
}
],
metadata: {
orderId: '12345'
}
})
});
const result = await response.json();
if (result.code === 0) {
// Get paymentUrl and redirect frontend to this address
console.log('Redirect user to:', result.data.paymentUrl);
return result.data.paymentUrl;
} else {
console.error('Error creating session:', result.message);
}
};
createSession();
import requests
import json
api_key = "<YOUR_API_KEY>"
url = "https://api.gstable.io/payment/v1/session/checkout/create"
payload = {
"accountId": "acc_example_12345678",
"settlementToken": "polygon::usdc",
"successUrl": "https://your-site.com/success",
"payerEmailRequired": 1,
"lineItems": [{
"itemType": "one_time",
"quantity": 1,
"unitPrice": 20000000, # $20.00 USD
"productData": {
"productName": "T-Shirt Dark Mode",
"imageUrl": "https://example.com/t-shirt.png"
}
}],
"metadata": {
"orderId": "12345"
}
}
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
result = response.json()
if result['code'] == 0:
print(f"Redirect user to: {result['data']['paymentUrl']}")
else:
print(f"Error: {result['message']}")
<?php
$api_key = '<YOUR_API_KEY>';
$url = 'https://api.gstable.io/payment/v1/session/checkout/create';
$data = [
'accountId' => 'acc_example_12345678',
'settlementToken' => 'polygon::usdc',
'successUrl' => 'https://your-site.com/success',
'payerEmailRequired' => 1,
'lineItems' => [[
'itemType' => 'one_time',
'quantity' => 1,
'unitPrice' => 20000000, // $20.00 USD
'productData' => [
'productName' => 'T-Shirt Dark Mode',
'imageUrl' => 'https://example.com/t-shirt.png'
]
]],
'metadata' => [
'orderId' => '12345'
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $api_key,
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
if ($result['code'] === 0) {
// Execute redirect in actual framework
// header('Location: ' . $result['data']['paymentUrl']);
echo "Redirect user to: " . $result['data']['paymentUrl'];
} else {
echo "Error: " . $result['message'];
}
?>
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
url := "https://api.gstable.io/payment/v1/session/checkout/create"
apiKey := "<YOUR_API_KEY>"
// Build LineItem
lineItems := []map[string]interface{}{
{
"itemType": "one_time",
"quantity": 1,
"unitPrice": 20000000, // $20.00 USD
"productData": map[string]string{
"productName": "T-Shirt Dark Mode",
"imageUrl": "https://example.com/t-shirt.png",
},
},
}
payload := map[string]interface{}{
"accountId": "acc_example_12345678",
"settlementToken": "polygon::usdc",
"successUrl": "https://your-site.com/success",
"payerEmailRequired": 1,
"lineItems": lineItems,
"metadata": map[string]string{
"orderId": "12345",
},
}
jsonValue, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonValue))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+apiKey)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
// Process Response
if code, ok := result["code"].(float64); ok && code == 0 {
data := result["data"].(map[string]interface{})
fmt.Printf("Redirect user to: %s\n", data["paymentUrl"])
} else {
fmt.Printf("Error: %s\n", result["message"])
}
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
// Import Jackson or Gson for JSON handling, logic demo only
public class CheckoutExample {
public static void main(String[] args) throws Exception {
String apiKey = "<YOUR_API_KEY>";
String endpoint = "https://api.gstable.io/payment/v1/session/checkout/create";
// Build JSON String (Recommend using Object Mapper)
String jsonBody = "{"
+ "\"accountId\":\"acc_example_12345678\","
+ "\"settlementToken\":\"polygon::usdc\","
+ "\"successUrl\":\"https://your-site.com/success\","
+ "\"payerEmailRequired\":1,"
+ "\"lineItems\":[{"
+ " \"itemType\":\"one_time\","
+ " \"quantity\":1,"
+ " \"unitPrice\":20000000,"
+ " \"productData\":{\"productName\":\"T-Shirt Dark Mode\"}"
+ "}],"
+ "\"metadata\":{\"orderId\":\"12345\"}"
+ "}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + apiKey)
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Response: " + response.body());
// Parse JSON: check code == 0, and get data.paymentUrl
}
}
4. Handle Response & Redirect
After a successful API call, a JSON containing the data object will be returned, where paymentUrl is the core field you need to use.
{
"code": 0,
"message": "success",
"data": {
"sessionId": "sess_example_payment_01",
"clientCode": "clt_l8ZBnpOSV9pVlaLK0dP5jsq5NzfqN3Vc",
"amount": 20000000,
"status": "initialized",
"paymentUrl": "https://pay.gstable.io/checkout/sess_example_payment_01"
}
}
Redirect User
After receiving this response in the backend, you need to extract data.paymentUrl and guide the user to redirect:
-
API Frontend-Backend Separation Mode: The backend returns
{ "url": data.paymentUrl }to the frontend, and the frontend executeswindow.location.href = url. -
Server-Side Rendering (SSR) Mode: The backend directly returns an HTTP 303 status code and sets
Location: <paymentUrl>in the Header.
Once redirected, users will enter the GStable cashier. Users can use stablecoins on any supported chain (such as USDC on Optimism or USDT on Ethereum) to pay, and the system will automatically convert it to the asset you specified in settlementToken and settle it to you.