curl --request POST \
--url https://api.pontisglobe.com/api/v1/gateway/payments/create \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--header 'x-signature: <x-signature>' \
--header 'x-timestamp: <x-timestamp>' \
--data '
{
"merchant_reference": "ORDER-1042",
"amount": "100.00",
"success_url": "<string>",
"fail_url": "<string>",
"currency": "USDT",
"expires_in_seconds": 43350
}
'import requests
url = "https://api.pontisglobe.com/api/v1/gateway/payments/create"
payload = {
"merchant_reference": "ORDER-1042",
"amount": "100.00",
"success_url": "<string>",
"fail_url": "<string>",
"currency": "USDT",
"expires_in_seconds": 43350
}
headers = {
"x-timestamp": "<x-timestamp>",
"x-signature": "<x-signature>",
"x-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-timestamp': '<x-timestamp>',
'x-signature': '<x-signature>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
merchant_reference: 'ORDER-1042',
amount: '100.00',
success_url: '<string>',
fail_url: '<string>',
currency: 'USDT',
expires_in_seconds: 43350
})
};
fetch('https://api.pontisglobe.com/api/v1/gateway/payments/create', 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.pontisglobe.com/api/v1/gateway/payments/create",
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([
'merchant_reference' => 'ORDER-1042',
'amount' => '100.00',
'success_url' => '<string>',
'fail_url' => '<string>',
'currency' => 'USDT',
'expires_in_seconds' => 43350
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>",
"x-signature: <x-signature>",
"x-timestamp: <x-timestamp>"
],
]);
$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.pontisglobe.com/api/v1/gateway/payments/create"
payload := strings.NewReader("{\n \"merchant_reference\": \"ORDER-1042\",\n \"amount\": \"100.00\",\n \"success_url\": \"<string>\",\n \"fail_url\": \"<string>\",\n \"currency\": \"USDT\",\n \"expires_in_seconds\": 43350\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-timestamp", "<x-timestamp>")
req.Header.Add("x-signature", "<x-signature>")
req.Header.Add("x-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.pontisglobe.com/api/v1/gateway/payments/create")
.header("x-timestamp", "<x-timestamp>")
.header("x-signature", "<x-signature>")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"merchant_reference\": \"ORDER-1042\",\n \"amount\": \"100.00\",\n \"success_url\": \"<string>\",\n \"fail_url\": \"<string>\",\n \"currency\": \"USDT\",\n \"expires_in_seconds\": 43350\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pontisglobe.com/api/v1/gateway/payments/create")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-timestamp"] = '<x-timestamp>'
request["x-signature"] = '<x-signature>'
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"merchant_reference\": \"ORDER-1042\",\n \"amount\": \"100.00\",\n \"success_url\": \"<string>\",\n \"fail_url\": \"<string>\",\n \"currency\": \"USDT\",\n \"expires_in_seconds\": 43350\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"merchant_reference": "ORDER-1042",
"status": "created",
"requested_amount": "100.00",
"requested_currency": "USDT",
"checkout_url": "https://pay.pontisglobe.com/c/pay_live_TOKEN",
"merchant_fee_amount": "0.50",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"ok": true,
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"merchant_reference": "ORDER-1042",
"status": "created",
"requested_amount": "100.00",
"requested_currency": "USDT",
"checkout_url": "https://pay.pontisglobe.com/c/pay_live_TOKEN",
"merchant_fee_amount": "0.50",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}/api/v1/gateway/payments/create
Open a payment and get a checkout URL to send your customer to.
curl --request POST \
--url https://api.pontisglobe.com/api/v1/gateway/payments/create \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--header 'x-signature: <x-signature>' \
--header 'x-timestamp: <x-timestamp>' \
--data '
{
"merchant_reference": "ORDER-1042",
"amount": "100.00",
"success_url": "<string>",
"fail_url": "<string>",
"currency": "USDT",
"expires_in_seconds": 43350
}
'import requests
url = "https://api.pontisglobe.com/api/v1/gateway/payments/create"
payload = {
"merchant_reference": "ORDER-1042",
"amount": "100.00",
"success_url": "<string>",
"fail_url": "<string>",
"currency": "USDT",
"expires_in_seconds": 43350
}
headers = {
"x-timestamp": "<x-timestamp>",
"x-signature": "<x-signature>",
"x-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-timestamp': '<x-timestamp>',
'x-signature': '<x-signature>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
merchant_reference: 'ORDER-1042',
amount: '100.00',
success_url: '<string>',
fail_url: '<string>',
currency: 'USDT',
expires_in_seconds: 43350
})
};
fetch('https://api.pontisglobe.com/api/v1/gateway/payments/create', 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.pontisglobe.com/api/v1/gateway/payments/create",
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([
'merchant_reference' => 'ORDER-1042',
'amount' => '100.00',
'success_url' => '<string>',
'fail_url' => '<string>',
'currency' => 'USDT',
'expires_in_seconds' => 43350
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>",
"x-signature: <x-signature>",
"x-timestamp: <x-timestamp>"
],
]);
$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.pontisglobe.com/api/v1/gateway/payments/create"
payload := strings.NewReader("{\n \"merchant_reference\": \"ORDER-1042\",\n \"amount\": \"100.00\",\n \"success_url\": \"<string>\",\n \"fail_url\": \"<string>\",\n \"currency\": \"USDT\",\n \"expires_in_seconds\": 43350\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-timestamp", "<x-timestamp>")
req.Header.Add("x-signature", "<x-signature>")
req.Header.Add("x-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.pontisglobe.com/api/v1/gateway/payments/create")
.header("x-timestamp", "<x-timestamp>")
.header("x-signature", "<x-signature>")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"merchant_reference\": \"ORDER-1042\",\n \"amount\": \"100.00\",\n \"success_url\": \"<string>\",\n \"fail_url\": \"<string>\",\n \"currency\": \"USDT\",\n \"expires_in_seconds\": 43350\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pontisglobe.com/api/v1/gateway/payments/create")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-timestamp"] = '<x-timestamp>'
request["x-signature"] = '<x-signature>'
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"merchant_reference\": \"ORDER-1042\",\n \"amount\": \"100.00\",\n \"success_url\": \"<string>\",\n \"fail_url\": \"<string>\",\n \"currency\": \"USDT\",\n \"expires_in_seconds\": 43350\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"merchant_reference": "ORDER-1042",
"status": "created",
"requested_amount": "100.00",
"requested_currency": "USDT",
"checkout_url": "https://pay.pontisglobe.com/c/pay_live_TOKEN",
"merchant_fee_amount": "0.50",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"ok": true,
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"merchant_reference": "ORDER-1042",
"status": "created",
"requested_amount": "100.00",
"requested_currency": "USDT",
"checkout_url": "https://pay.pontisglobe.com/c/pay_live_TOKEN",
"merchant_fee_amount": "0.50",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "insufficient_funds",
"message": "Insufficient available balance. Available: 5.00 USDT"
}
}{ "data": "<aes-256-gcm ciphertext>" } — see Authentication.authorization header —
creating a payment link moves no money on its own, so it is authenticated by your API key, request
signature and IP allowlist alone. You can skip the login call entirely for a payin-only
integration.success_url and fail_url hosts must be registered on your merchant profile before they will be
accepted — an unregistered host is rejected with redirect_domain_not_allowed before a payment is
created. Ask your account manager to add them.Idempotency
Reusing amerchant_reference returns the existing payment rather than creating a second one.
A retry after a network timeout is safe and gives you back the original checkout_url.
The status code is how you tell the two apart: 201 means you just created it, 200 means this
merchant_reference was already used and you are getting the original payment — and its original
checkout_url — back.
checkout_url is a bearer credential. Anyone holding it can see the order amount and the
deposit address. Send it to your customer directly — do not log it, email it to a shared inbox, or
put it anywhere indexable.Example request
const payin = await call('/api/v1/gateway/payments/create', {
merchant_reference: 'ORDER-1042',
amount: '100.00',
currency: 'USDT',
success_url: 'https://shop.example.com/thanks',
fail_url: 'https://shop.example.com/cancelled',
})
// Send the customer here.
redirect(payin.data.checkout_url)
payin = call("/api/v1/gateway/payments/create", {
"merchant_reference": "ORDER-1042",
"amount": "100.00",
"currency": "USDT",
"success_url": "https://shop.example.com/thanks",
"fail_url": "https://shop.example.com/cancelled",
})
redirect(payin["data"]["checkout_url"])
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | validation_error | A field failed validation — the message names it |
| 400 | bad_request | Bad envelope: missing or skewed x-timestamp, or a body we could not decrypt |
| 401 | unauthorized | Missing or invalid API key or signature, or API access is disabled |
| 403 | forbidden | Your IP is not allow-listed, or your account does not hold the payin product |
| 403 | profile_missing | No merchant profile has been set up for your account yet |
| 403 | gateway_not_enabled | The product is held but payins are switched off on your merchant profile |
| 409 | wallet_frozen | Your wallet is frozen, so nothing can be credited to it |
| 422 | redirect_domain_not_allowed | A redirect host is not registered on your merchant profile |
| 422 | amount_below_minimum | Below the minimum payment amount configured for your account |
| 429 | rate_limited | Over 300 creates per minute — back off and retry |
| 503 | no_provider_available | We cannot open a payment right now. Retry with backoff |
| 503 | pricing_unavailable | Fees are not configured for your account — contact us |
{
"ok": false,
"request_id": "8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934",
"error": {
"code": "redirect_domain_not_allowed",
"message": "Redirect URL host is not in this account’s allowed domains"
}
}
request_id when you contact support — it identifies the exact request in our logs.503 is about us, not your request: retry the same payload with backoff and it will succeed once
the condition clears. A 4xx will not change on retry.
See Errors for the envelope shape shared by every endpoint.Authorizations
Identifies your account. Issued from Developer Tools in the dashboard.
Headers
Unix epoch in seconds — not milliseconds. Must be within ±5 minutes of our clock, which is what makes a captured request unusable later. Keep your client's clock NTP-synced.
1748023400
HMAC-SHA256 over the signing string, hex encoded. The timestamp is part of what is signed, so a replayed body cannot be re-dated. See https://docs.pontisglobe.com/authentication for how it is built.
"2f8a9b4c1d7e0a3f6b8c2d5e9f1a4b7c0d3e6f9a2b5c8d1e4f7a0b3c6d9e2f5a"
Body
Your own order id. Also the idempotency key.
1 - 128"ORDER-1042"
A positive decimal string, at most 2 decimal places. More than two is rejected rather than rounded — a sub-cent order would have the payer charged something the merchant's own order does not say.
^\d+(\.\d+)?$"100.00"
https only, no embedded credentials, and the host must be on your
account's allowed domains.
USDT 5 minutes to 24 hours. Also how long a deposit address stays open.
300 <= x <= 86400