Documentation Index
Fetch the complete documentation index at: https://developer.forebit.io/llms.txt
Use this file to discover all available pages before exploring further.
Forebit Payments — Guide for AI Agents
This page contains everything an AI agent (Claude, Cursor, Codex, or any LLM-based coding tool) needs to integrate Forebit Payments into a website. Copy-paste this entire page into your AI agent’s context.
You are integrating Forebit Payments, a cryptocurrency payment processing API. Forebit provides a hosted checkout page — you create a payment via the API, redirect the customer to the checkout URL, and listen for webhook events to confirm payment.
Architecture Overview
The integration flow is:
- Your server creates a payment via the REST API
- The API returns a
url to a Forebit-hosted checkout page
- You redirect the customer to that URL
- The customer selects a cryptocurrency and pays
- Forebit sends a webhook to your server when the payment status changes
- Your server verifies the webhook signature and updates the order
- Optionally, the customer is redirected back to your site via
redirectUrl
There is no client-side SDK. All API calls happen server-side. The checkout UI is fully hosted by Forebit.
Credentials
Obtain these from the Forebit dashboard:
| Credential | Where to find it | Purpose |
|---|
| Business ID | Payments → Settings → Developer | Identifies your business in API URLs |
| API Key | Payments → Settings → Developer | Bearer token for API authentication |
| Webhook Secret | Developer → Webhooks | whsec_... prefix, used with Svix to verify webhook signatures |
Environment variables
FOREBIT_BUSINESS_ID=your_business_id
FOREBIT_API_KEY=your_payments_api_key
FOREBIT_WEBHOOK_SECRET=whsec_...
API Basics
Base URL
https://prod-payments-api.forebit.io
All requests must use HTTPS.
Authentication
Every request requires a Bearer token:
Authorization: Bearer YOUR_API_KEY
Success:
{
"data": { ... },
"message": null,
"errors": null
}
Error (RFC 7807 ProblemDetails):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"detail": "Validation failed"
}
HTTP status codes
| Status | Meaning |
|---|
200 | Success |
400 | Invalid parameters or validation error |
401 | Invalid or missing API key |
403 | Insufficient permissions for this business |
404 | Payment or business not found |
Endpoints
All endpoints are scoped to a business:
| Method | Endpoint | Description |
|---|
POST | /v1/businesses/{businessId}/payments | Create a new payment |
GET | /v1/businesses/{businessId}/payments/{paymentId} | Get a single payment |
GET | /v1/businesses/{businessId}/payments | List payments (paginated) |
PUT | /v1/businesses/{businessId}/payments/{paymentId}/note | Update internal note |
Creating a Payment
POST /v1/businesses/{businessId}/payments
Request body
| Field | Type | Required | Description |
|---|
currency | string | Yes | ISO 4217 currency code (e.g. USD, EUR) |
amount | number | Yes | Payment amount (minimum 0.5) |
name | string | No | Display name shown to customer on checkout page |
description | string | No | Internal description, not visible to customers |
customerEmail | string (email) | No | Customer email for receipts and status updates |
customerIp | string | No | Customer IP address. Auto-detected from checkout page visit if omitted |
customerUserAgent | string | No | Customer user-agent. Auto-detected from checkout page visit if omitted |
redirectUrl | string (URI) | No | URL to redirect the customer after payment completes |
notifyUrl | string (URI) | No | Webhook URL for this specific payment (overrides default) |
metadata | object | No | Arbitrary key-value string pairs stored with the payment. Use this to attach your internal order ID |
paymentMethods | object | No | Restrict which payment methods are available to the customer |
feeTransfers | array | No | Fee transfer configuration |
Example request
curl -X POST https://prod-payments-api.forebit.io/v1/businesses/{businessId}/payments \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"currency": "USD",
"amount": 25.00,
"name": "Order #1234",
"description": "Premium plan subscription",
"customerEmail": "customer@example.com",
"redirectUrl": "https://yoursite.com/thank-you",
"notifyUrl": "https://yoursite.com/webhooks/forebit",
"metadata": {
"orderId": "1234",
"plan": "premium"
}
}'
Example response
{
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"url": "https://pay.forebit.io/payment/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
},
"message": null,
"errors": null
}
id — UUID of the payment, use this to query the payment later
url — hosted checkout page URL, redirect the customer here
Restricting payment methods
Pass the paymentMethods object to control which cryptocurrencies are available. If omitted, all methods configured for your business are enabled.
{
"paymentMethods": {
"FOREBIT_CRYPTO": ["BITCOIN", "ETHEREUM", "SOLANA"],
"CONTRACT_CRYPTO": ["CONTRACT_ERC20_USDT", "CONTRACT_ERC20_USDC"]
}
}
Charge types:
| Type | Description |
|---|
FOREBIT_CRYPTO | Native coins and tokens via Forebit wallets |
CONTRACT_CRYPTO | ERC-20 tokens via smart contract |
CONTRACT_TRX | TRC-20 tokens via smart contract |
NONE | No crypto payment method |
Available coins per charge type:
- FOREBIT_CRYPTO:
BITCOIN, ETHEREUM, LITECOIN, BITCOIN_CASH, ETH_USD_COIN, ETH_TETHER, MONERO, BNB, ETH_BUSD, ETH_MATIC, ETH_SHIBA_INU, ETH_APE_COIN, ETH_CRONOS, ETH_DAI, ETH_UNISWAP, TRON, TRX_TETHER, TRX_USD_C, SOLANA, SOL_TETHER, SOL_USD_COIN, TON
- CONTRACT_CRYPTO:
CONTRACT_ERC20_ETH, CONTRACT_ERC20_USDT, CONTRACT_ERC20_USDC
- CONTRACT_TRX:
CONTRACT_TRC20_TRX, CONTRACT_TRC20_USDT, CONTRACT_TRC20_USDC
Retrieving a Payment
GET /v1/businesses/{businessId}/payments/{paymentId}
curl https://prod-payments-api.forebit.io/v1/businesses/{businessId}/payments/{paymentId} \
-H "Authorization: Bearer YOUR_API_KEY"
Response fields
| Field | Type | Description |
|---|
id | string (UUID) | Payment identifier |
name | string | Display name |
description | string | Internal description |
endAmount | number | Final payment amount |
prePaymentAmount | number | Amount before payment processing |
currency | string | ISO 4217 currency code |
status | PaymentStatus | Current payment status |
createdAt | date-time | When the payment was created |
expiresAt | date-time | When the payment expires |
timeline | array | Status change history |
customer | object | Customer details including email and IP info |
metadata | object | Custom key-value pairs you attached |
selectedPaymentMethod | PaymentMethod | Method chosen by the customer |
forebitCryptoCharge | object | Forebit crypto charge details (if applicable) |
contractCharge | object | Contract charge details (if applicable) |
forebitFee | number | Fee amount |
note | string | Internal note |
netAmountUsd | number | Net amount in USD |
Listing Payments
GET /v1/businesses/{businessId}/payments
Query parameters
| Parameter | Type | Description |
|---|
PageNumber | integer | Page number |
PageSize | integer | Results per page |
fromTime | date-time | Start of date range |
toTime | date-time | End of date range |
statuses | array | Filter by status (repeat parameter for multiple) |
cryptoCoins | array | Filter by cryptocurrency |
fromAmount | number | Minimum amount |
toAmount | number | Maximum amount |
searchString | string | Free-text search across description, name, note, or customer email |
Example:
curl "https://prod-payments-api.forebit.io/v1/businesses/{businessId}/payments?PageSize=20&statuses=COMPLETED&statuses=PENDING" \
-H "Authorization: Bearer YOUR_API_KEY"
Payment Statuses
| Status | Description |
|---|
AWAITING_PAYMENT | Payment created, waiting for customer to pay |
PENDING | Payment detected on-chain, awaiting confirmation |
PROCESSING | Payment is being processed |
UNDERPAID | Customer sent less than the required amount |
COMPLETED | Payment confirmed and completed — fulfill the order |
FAILED | Payment failed |
CANCELLED | Payment was cancelled |
EXPIRED | Payment expired before completion |
Webhooks
Forebit uses Svix for webhook delivery. Svix provides automatic retries, signature validation, and delivery logs.
Webhook events
| Event | Description |
|---|
PAYMENT_CREATED | Payment was created |
PAYMENT_METHOD_SELECTED | Customer selected a payment method |
PAYMENT_PENDING | Payment detected, awaiting confirmation |
PAYMENT_UNDERPAID | Customer sent less than required |
PAYMENT_COMPLETED | Payment confirmed — this is the event to fulfill orders on |
PAYMENT_EXPIRED | Payment expired |
PAYMENT_CANCELLED | Payment was cancelled |
Webhook payload structure
{
"EventType": "PAYMENT_COMPLETED",
"ForPaymentEvents": {
"Id": "78d1cc6a-2e46-421b-b03b-3c307bfbd1bc",
"BusinessId": 1001,
"Name": "Order #1234",
"Description": "",
"EndAmount": 25.00,
"PrePaymentAmount": 25.00,
"Currency": "USD",
"Status": "COMPLETED",
"CreatedAt": "2025-08-14T09:18:56.295788Z",
"ExpiresAt": "2025-08-14T09:48:56.295788Z",
"Timeline": [
{ "Time": "2025-08-14T09:18:56Z", "PaymentStatus": "AWAITING_PAYMENT" },
{ "Time": "2025-08-14T09:20:40Z", "PaymentStatus": "PENDING" },
{ "Time": "2025-08-14T09:20:40Z", "PaymentStatus": "COMPLETED" }
],
"Customer": {
"Id": 68,
"Email": "customer@example.com",
"IpAddresses": [
{
"City": "New York",
"Ip": "203.0.113.50",
"Country": "United States",
"RiskScore": 0,
"ConnectionType": "RESIDENTIAL",
"ISP": "Example ISP",
"DateCreated": "2025-07-21T09:13:11Z"
}
]
},
"SelectedPaymentMethod": "FOREBIT_CRYPTO",
"ForebitCryptoCharge": {
"Amount": 0.00025,
"CoinName": "BITCOIN",
"ExchangeRate": 100000.00,
"IsUnderpaid": false,
"Address": "bc1q...",
"Transaction": {
"Amount": 0.00025,
"ToAddress": "bc1q...",
"Id": "txhash...",
"Confirmations": 3,
"Network": "BTC",
"FromAddress": "bc1qsender...",
"TokenName": "BITCOIN"
},
"WalletName": "main"
},
"ForebitFee": 0.50,
"RedirectUrl": "https://yoursite.com/thank-you"
}
}
Important: Webhook field names use PascalCase (e.g. EventType, ForPaymentEvents, EndAmount), while the REST API responses use camelCase (e.g. endAmount, currency).
Webhook payload TypeScript types
interface BaseWebhookResponse {
EventType: string;
ForPaymentEvents?: PaymentForWebhookResponse | null;
}
interface PaymentForWebhookResponse {
Id: string;
BusinessId: number;
Name?: string;
Description?: string;
EndAmount: number;
PrePaymentAmount: number;
Currency: string;
Status: PaymentStatus;
CreatedAt: string;
ExpiresAt: string;
Timeline: { Time: string; PaymentStatus: PaymentStatus }[];
Customer?: {
Id: number;
Email: string;
IpAddresses: {
City?: string;
Ip: string;
Country?: string;
RiskScore?: number;
ConnectionType: string;
ISP?: string;
DateCreated: string;
}[];
} | null;
Metadata?: Record<string, string> | null;
SelectedPaymentMethod?: PaymentMethod | null;
ForebitCryptoCharge?: {
Amount: number;
CoinName: string;
ExchangeRate: number;
IsUnderpaid: boolean;
Address: string;
Transaction?: {
Amount: number;
ToAddress: string;
Id: string;
Confirmations: number;
BlockNumber?: string;
Network?: string;
FromAddress?: string;
TokenName?: string;
} | null;
WalletName: string;
} | null;
ContractCharge?: {
Amount: number;
ExchangeRate: number;
IsUnderpaid: boolean;
Address: string;
Transaction: {
Amount: number;
ToAddress: string;
Id: string;
Confirmations: number;
BlockNumber?: string;
Network?: string;
FromAddress?: string;
TokenName?: string;
};
WalletName: string;
CoinName: string;
} | null;
ForebitFee?: number;
RedirectUrl?: string;
}
type PaymentStatus =
| 'AWAITING_PAYMENT' | 'PENDING' | 'PROCESSING'
| 'UNDERPAID' | 'COMPLETED' | 'FAILED'
| 'CANCELLED' | 'EXPIRED';
type PaymentMethod = 'FOREBIT_CRYPTO' | 'CONTRACT_CRYPTO' | 'CONTRACT_TRX' | 'NONE';
Verifying webhook signatures
Use the Svix library to verify webhook signatures. This is critical for security — never process a webhook without verifying the signature first.
Required headers from the webhook request: svix-id, svix-timestamp, svix-signature.
Node.js:
import { Webhook } from "svix";
const wh = new Webhook(process.env.FOREBIT_WEBHOOK_SECRET);
// Inside your webhook handler:
// payload = raw request body as a string
// headers = object with svix-id, svix-timestamp, svix-signature
const event = wh.verify(payload, headers);
Python:
from svix.webhooks import Webhook
wh = Webhook(os.environ["FOREBIT_WEBHOOK_SECRET"])
# payload = raw request body as bytes
# headers = dict with svix-id, svix-timestamp, svix-signature
event = wh.verify(payload, headers)
Install: npm install svix (Node.js) or pip install svix (Python).
Full Integration Examples
Node.js (Express)
import express from "express";
import { Webhook } from "svix";
const app = express();
const FOREBIT_API_KEY = process.env.FOREBIT_API_KEY;
const FOREBIT_BUSINESS_ID = process.env.FOREBIT_BUSINESS_ID;
const FOREBIT_WEBHOOK_SECRET = process.env.FOREBIT_WEBHOOK_SECRET;
const BASE_URL = "https://prod-payments-api.forebit.io";
// 1. Create a payment and redirect to checkout
app.post("/checkout", async (req, res) => {
const { orderId, amount, email } = req.body;
const response = await fetch(
`${BASE_URL}/v1/businesses/${FOREBIT_BUSINESS_ID}/payments`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${FOREBIT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
currency: "USD",
amount,
name: `Order #${orderId}`,
customerEmail: email,
redirectUrl: "https://yoursite.com/thank-you",
notifyUrl: "https://yoursite.com/webhooks/forebit",
metadata: { orderId },
}),
}
);
const result = await response.json();
if (!response.ok) {
return res.status(400).json({ error: result });
}
// Save result.data.id to your database linked to the order
// Then redirect the customer to checkout
res.json({ checkoutUrl: result.data.url });
});
// 2. Handle webhooks — use raw body for signature verification
app.post(
"/webhooks/forebit",
express.raw({ type: "application/json" }),
(req, res) => {
const wh = new Webhook(FOREBIT_WEBHOOK_SECRET);
let event;
try {
event = wh.verify(req.body.toString(), {
"svix-id": req.headers["svix-id"],
"svix-timestamp": req.headers["svix-timestamp"],
"svix-signature": req.headers["svix-signature"],
});
} catch (err) {
console.error("Webhook verification failed:", err.message);
return res.status(400).send("Invalid signature");
}
const { EventType, ForPaymentEvents: payment } = event;
switch (EventType) {
case "PAYMENT_COMPLETED":
// Fulfill the order using payment.Metadata.orderId
console.log(`Payment ${payment.Id} completed for ${payment.EndAmount} ${payment.Currency}`);
// Update your database: mark order as paid
break;
case "PAYMENT_EXPIRED":
// Handle expired payment
console.log(`Payment ${payment.Id} expired`);
break;
case "PAYMENT_UNDERPAID":
// Handle underpaid payment
console.log(`Payment ${payment.Id} underpaid`);
break;
}
res.status(200).send("OK");
}
);
// Use json parsing for all other routes
app.use(express.json());
app.listen(3000);
Python (Flask)
import os
import requests
from flask import Flask, request, jsonify
from svix.webhooks import Webhook
app = Flask(__name__)
FOREBIT_API_KEY = os.environ["FOREBIT_API_KEY"]
FOREBIT_BUSINESS_ID = os.environ["FOREBIT_BUSINESS_ID"]
FOREBIT_WEBHOOK_SECRET = os.environ["FOREBIT_WEBHOOK_SECRET"]
BASE_URL = "https://prod-payments-api.forebit.io"
@app.route("/checkout", methods=["POST"])
def checkout():
data = request.json
order_id = data["orderId"]
amount = data["amount"]
email = data.get("email")
resp = requests.post(
f"{BASE_URL}/v1/businesses/{FOREBIT_BUSINESS_ID}/payments",
headers={
"Authorization": f"Bearer {FOREBIT_API_KEY}",
"Content-Type": "application/json",
},
json={
"currency": "USD",
"amount": amount,
"name": f"Order #{order_id}",
"customerEmail": email,
"redirectUrl": "https://yoursite.com/thank-you",
"notifyUrl": "https://yoursite.com/webhooks/forebit",
"metadata": {"orderId": order_id},
},
)
result = resp.json()
if resp.status_code != 200:
return jsonify({"error": result}), 400
# Save result["data"]["id"] to your database
return jsonify({"checkoutUrl": result["data"]["url"]})
@app.route("/webhooks/forebit", methods=["POST"])
def webhook():
wh = Webhook(FOREBIT_WEBHOOK_SECRET)
try:
event = wh.verify(
request.get_data(as_text=True),
{
"svix-id": request.headers.get("svix-id"),
"svix-timestamp": request.headers.get("svix-timestamp"),
"svix-signature": request.headers.get("svix-signature"),
},
)
except Exception as e:
print(f"Webhook verification failed: {e}")
return "Invalid signature", 400
event_type = event["EventType"]
payment = event["ForPaymentEvents"]
if event_type == "PAYMENT_COMPLETED":
order_id = payment.get("Metadata", {}).get("orderId")
print(f"Payment {payment['Id']} completed — fulfill order {order_id}")
# Update your database: mark order as paid
elif event_type == "PAYMENT_EXPIRED":
print(f"Payment {payment['Id']} expired")
return "OK", 200
Next.js (App Router)
// app/api/checkout/route.ts
import { NextResponse } from "next/server";
const FOREBIT_API_KEY = process.env.FOREBIT_API_KEY!;
const FOREBIT_BUSINESS_ID = process.env.FOREBIT_BUSINESS_ID!;
export async function POST(req: Request) {
const { orderId, amount, email } = await req.json();
const response = await fetch(
`https://prod-payments-api.forebit.io/v1/businesses/${FOREBIT_BUSINESS_ID}/payments`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${FOREBIT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
currency: "USD",
amount,
name: `Order #${orderId}`,
customerEmail: email,
redirectUrl: "https://yoursite.com/thank-you",
notifyUrl: "https://yoursite.com/api/webhooks/forebit",
metadata: { orderId },
}),
}
);
const result = await response.json();
if (!response.ok) {
return NextResponse.json({ error: result }, { status: 400 });
}
return NextResponse.json({ checkoutUrl: result.data.url });
}
// app/api/webhooks/forebit/route.ts
import { Webhook } from "svix";
const FOREBIT_WEBHOOK_SECRET = process.env.FOREBIT_WEBHOOK_SECRET!;
export async function POST(req: Request) {
const body = await req.text();
const headers = {
"svix-id": req.headers.get("svix-id") ?? "",
"svix-timestamp": req.headers.get("svix-timestamp") ?? "",
"svix-signature": req.headers.get("svix-signature") ?? "",
};
const wh = new Webhook(FOREBIT_WEBHOOK_SECRET);
let event: any;
try {
event = wh.verify(body, headers);
} catch {
return new Response("Invalid signature", { status: 400 });
}
const { EventType, ForPaymentEvents: payment } = event;
if (EventType === "PAYMENT_COMPLETED") {
const orderId = payment.Metadata?.orderId;
// Fulfill the order in your database
}
return new Response("OK", { status: 200 });
}
Best Practices
Security
- Always verify webhook signatures using Svix before processing any webhook event. Never trust the payload without verification.
- Keep your API key server-side only. Never expose it in client-side code, browser JavaScript, or mobile apps.
- Use HTTPS for all webhook endpoints. Forebit will not deliver webhooks to HTTP URLs in production.
- Store the webhook secret securely in environment variables, never hardcoded.
Payment creation
- Always store the payment
id from the create response in your database, linked to your internal order. You need it to reconcile webhooks and query payment status.
- Use
metadata to attach your internal order ID, user ID, or any reference data. This data is returned in webhooks and GET requests, making reconciliation easy.
- Set
redirectUrl so the customer returns to your site after payment. Without it, they stay on the Forebit checkout page.
- Set
notifyUrl per-payment if you have multiple webhook endpoints, or rely on the default configured in the dashboard.
- Set
customerEmail so the customer receives email receipts and status updates.
- Minimum amount is
0.5 in your chosen currency.
Webhook handling
- Respond with
200 quickly. Process the webhook asynchronously if your fulfillment logic is slow. Svix will retry on non-2xx responses.
- Make your webhook handler idempotent. You may receive the same event more than once due to retries. Use the payment
Id to deduplicate.
- Only fulfill orders on
PAYMENT_COMPLETED. Do not fulfill on PENDING or PROCESSING — these are intermediate states.
- Handle
PAYMENT_EXPIRED and PAYMENT_CANCELLED to clean up pending orders in your system.
- Use the raw request body for signature verification. Parsing the JSON first and re-serializing it will break the signature.
Error handling
- Check for non-200 responses from the API and handle them gracefully.
- API errors use RFC 7807 ProblemDetails format with
type, title, status, and detail fields.
- If a payment creation fails, show the user an error and let them retry. Do not create duplicate payments — check your database first.
Testing
- Use small amounts (minimum
0.5) for test payments.
- Use the Svix CLI or dashboard to replay webhooks to your endpoint during development.
- Use a tool like ngrok to expose your local webhook endpoint during development.
Supported Cryptocurrencies (Full List)
| Coin | Identifier | Network |
|---|
| Bitcoin | BITCOIN | BTC |
| Ethereum | ETHEREUM | ETHEREUM |
| Litecoin | LITECOIN | LTC |
| Bitcoin Cash | BITCOIN_CASH | BTC |
| USDC (ERC-20) | ETH_USD_COIN | ETHEREUM |
| USDT (ERC-20) | ETH_TETHER | ETHEREUM |
| Monero | MONERO | — |
| BNB | BNB | ETHEREUM |
| DAI (ERC-20) | ETH_DAI | ETHEREUM |
| Uniswap (ERC-20) | ETH_UNISWAP | ETHEREUM |
| MATIC (ERC-20) | ETH_MATIC | ETHEREUM |
| SHIB (ERC-20) | ETH_SHIBA_INU | ETHEREUM |
| APE (ERC-20) | ETH_APE_COIN | ETHEREUM |
| CRO (ERC-20) | ETH_CRONOS | ETHEREUM |
| BUSD (ERC-20) | ETH_BUSD | ETHEREUM |
| Tron | TRON | TRON |
| USDT (TRC-20) | TRX_TETHER | TRON |
| USDC (TRC-20) | TRX_USD_C | TRON |
| Solana | SOLANA | SOLANA |
| USDT (Solana) | SOL_TETHER | SOLANA |
| USDC (Solana) | SOL_USD_COIN | SOLANA |
| TON | TON | — |
| Contract ETH | CONTRACT_ERC20_ETH | ETHEREUM |
| Contract USDT (ERC-20) | CONTRACT_ERC20_USDT | ETHEREUM |
| Contract USDC (ERC-20) | CONTRACT_ERC20_USDC | ETHEREUM |
| Contract TRX | CONTRACT_TRC20_TRX | TRON |
| Contract USDT (TRC-20) | CONTRACT_TRC20_USDT | TRON |
| Contract USDC (TRC-20) | CONTRACT_TRC20_USDC | TRON |
Networks: ETHEREUM, TRON, BTC, LTC, SOLANA
Quick Reference
Base URL: https://prod-payments-api.forebit.io
Auth header: Authorization: Bearer YOUR_API_KEY
Create payment: POST /v1/businesses/{businessId}/payments
Get payment: GET /v1/businesses/{businessId}/payments/{paymentId}
List payments: GET /v1/businesses/{businessId}/payments
Update note: PUT /v1/businesses/{businessId}/payments/{paymentId}/note
Webhook lib: svix (npm install svix / pip install svix)
Fulfill on: PAYMENT_COMPLETED event only
Min amount: 0.5 (in chosen currency)