Invoices
Creating, retrieving, and deleting payment invoices in the PS Wallet Pay API: createInvoice, getInvoices, deleteInvoice.
On this page
An invoice is a payment request that a user opens via a link and pays in PS Wallet. The payment amount minus the fee is credited to the app balance, and an invoice_paid webhook is sent to your server.
An invoice can be issued in a coin (USDT, USDT-TRC20, TRX, etc.) or in fiat (USD, RUB), in which case the user chooses the coin to pay with. For coin codes and amount formatting rules, see Coins and amounts.
Invoice statuses
| Status | Meaning |
|---|---|
active | The invoice is awaiting payment. |
paid | The invoice is paid and the funds are credited to the app balance. |
expired | The validity period (expires_in) has ended; the invoice can no longer be paid. |
An invoice deleted via deleteInvoice can't be paid and no longer appears in getInvoices.
createInvoice
Create a payment invoice. POST only. Returns Invoice.
| Parameter | Type | Description |
|---|---|---|
currency_type | String | Optional. crypto (default) or fiat. |
asset | String | Required if currency_type=crypto. Invoice coin: USDT (any network), USDT-TRC20, USDT-BEP20, USDT-ERC20, USDT-TON, XAUT, TRX, BNB, ETH, GRAM. |
fiat | String | Required if currency_type=fiat. Amount currency: USD or RUB. |
accepted_assets | String | Optional, fiat only. Coins accepted for payment, comma-separated, for example USDT,TRX. In JSON you can also pass an array. Default: USDT,TRX,BNB,ETH,GRAM,RUB (of these, only the ones currently available). |
amount | String | Required. Amount in the asset coin or in the fiat currency, for example 125.50. |
description | String | Optional. Description shown to the user. Up to 1024 characters. |
hidden_message | String | Optional. Message the user sees after payment. Up to 2048 characters. |
paid_btn_name | String | Optional. Button on the screen after payment: viewItem, openChannel, openBot, or callback (see below). |
paid_btn_url | String | Required if paid_btn_name is specified. Button link, starts with https:// or http://, up to 512 characters. |
payload | String | Optional. Any data of your own (for example, an order number), up to 4 KB. Returned in the invoice and in the webhook. |
allow_comments | Boolean | Optional. Allow the user to leave a comment with the payment. Default: true. |
allow_anonymous | Boolean | Optional. Allow anonymous payment: the payer's name won't be visible in the app history. Default: true. |
expires_in | Number | Optional. Invoice lifetime in seconds, from 1 to 2678400 (31 days). By default, the invoice never expires. |
Boolean parameters accept true/false as well as 1/0, which is convenient for application/x-www-form-urlencoded.
Request example
curl https://pay.pswallet.org/api/createInvoice \
-H "PSWallet-Pay-API-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"asset": "USDT",
"amount": "12.5",
"description": "Подписка на месяц",
"payload": "order-1042",
"expires_in": 3600
}'// Node.js 18+ (built-in fetch)
const response = await fetch("https://pay.pswallet.org/api/createInvoice", {
method: "POST",
headers: {
"PSWallet-Pay-API-Token": process.env.PSWALLET_PAY_TOKEN,
"Content-Type": "application/json",
},
body: JSON.stringify({
asset: "USDT",
amount: "12.5",
description: "Подписка на месяц",
payload: "order-1042",
expires_in: 3600,
}),
});
const data = await response.json();
if (!data.ok) throw new Error(data.error.name);
const invoice = data.result;
// store invoice.invoice_id alongside the order and send the link to the user
console.log(invoice.bot_invoice_url);import os
import requests
response = requests.post(
"https://pay.pswallet.org/api/createInvoice",
headers={"PSWallet-Pay-API-Token": os.environ["PSWALLET_PAY_TOKEN"]},
json={
"asset": "USDT",
"amount": "12.5",
"description": "Подписка на месяц",
"payload": "order-1042",
"expires_in": 3600,
},
timeout=15,
)
data = response.json()
if not data["ok"]:
raise RuntimeError(data["error"]["name"])
invoice = data["result"]
# store invoice["invoice_id"] alongside the order and send the link to the user
print(invoice["bot_invoice_url"])Response:
{
"ok": true,
"result": {
"invoice_id": 528,
"hash": "IVq3Lm9TzR4wXkPa",
"currency_type": "crypto",
"asset": "USDT",
"amount": "12.5",
"bot_invoice_url": "https://t.me/pswallet?start=IVq3Lm9TzR4wXkPa",
"mini_app_invoice_url": "https://t.me/pswallet?startapp=IVq3Lm9TzR4wXkPa",
"web_app_invoice_url": "https://t.me/pswallet?startapp=IVq3Lm9TzR4wXkPa",
"pay_url": "https://t.me/pswallet?start=IVq3Lm9TzR4wXkPa",
"description": "Подписка на месяц",
"status": "active",
"created_at": "2026-10-28T15:51:21.000+00:00",
"allow_comments": true,
"allow_anonymous": true,
"expiration_date": "2026-10-28T16:51:21.000+00:00",
"payload": "order-1042",
"paid_anonymously": false
}
}Send the user bot_invoice_url (the invoice opens in the bot chat with a payment button) or mini_app_invoice_url (opens the payment screen directly in the mini app).
Pass the order number in payload: it will be returned in the invoice_paid webhook, so you can easily find the order without a separate mapping table.
Invoice in dollars or rubles
To issue an invoice in fiat, pass currency_type=fiat, the fiat currency, and, if needed, a list of coins in accepted_assets:
{
"currency_type": "fiat",
"fiat": "USD",
"amount": "9.99",
"accepted_assets": "USDT,TRX",
"description": "Премиум на месяц"
}The user chooses a coin from the allowed ones, and the amount is converted at the exchange rate at the time of payment. For details, see Coins and amounts.
If accepted_assets contains a coin that is currently unavailable, the PARAM_ACCEPTED_ASSETS_INVALID error is returned. Rubles (RUB) are currently not accepted for payment, and a list consisting only of RUB will also return this error.
Button after payment
After payment, the user sees a screen with the hidden_message message (if set) and a button that leads to paid_btn_url:
paid_btn_name | Button text |
|---|---|
viewItem | "Open item" |
openChannel | "Open channel" |
openBot | "Open bot" |
callback | "Return" |
createInvoice errors
The response code is 400 unless stated otherwise.
PARAM_CURRENCY_TYPE_INVALID—currency_typeis neithercryptonorfiat.PARAM_ASSET_REQUIRED,PARAM_ASSET_INVALID— theassetcoin is missing, unknown, or currently unavailable.PARAM_FIAT_REQUIRED,PARAM_FIAT_INVALID— thefiatcurrency is missing or unknown.PARAM_ACCEPTED_ASSETS_INVALID— invalidaccepted_assetslist.PARAM_AMOUNT_REQUIRED,PARAM_AMOUNT_INVALID— the amount is missing, is not greater than zero, or has more decimal places than the coin allows.PARAM_DESCRIPTION_INVALID,PARAM_HIDDEN_MESSAGE_INVALID,PARAM_PAYLOAD_INVALID— the text is longer than allowed.PARAM_PAID_BTN_NAME_INVALID,PARAM_PAID_BTN_URL_REQUIRED,PARAM_PAID_BTN_URL_INVALID— invalid button after payment.PARAM_ALLOW_COMMENTS_INVALID,PARAM_ALLOW_ANONYMOUS_INVALID— not a boolean value.PARAM_EXPIRES_IN_INVALID—expires_inis not an integer from 1 to 2678400.403 APP_FROZEN— the app is frozen.
getInvoices
List of the app's invoices, newest first. Deleted invoices are not returned. Returns an object { "items": [Invoice, …] }.
| Parameter | Type | Description |
|---|---|---|
asset | String | Optional. Only invoices in this coin (by the invoice's asset field, not by the payment coin). |
fiat | String | Optional. Only invoices in this fiat currency. |
invoice_ids | String | Optional. Invoice IDs, comma-separated (the first 1000 are used). |
status | String | Optional. active, paid, or expired. Default: all. |
offset | Number | Optional. How many invoices to skip. Default: 0. |
count | Number | Optional. How many to return, from 1 to 1000. Default: 100. |
curl "https://pay.pswallet.org/api/getInvoices?status=paid&count=10" \
-H "PSWallet-Pay-API-Token: $TOKEN"Response:
{
"ok": true,
"result": {
"items": [
{
"invoice_id": 528,
"hash": "IVq3Lm9TzR4wXkPa",
"currency_type": "crypto",
"asset": "USDT",
"amount": "12.5",
"status": "paid",
"paid_asset": "USDT-TRC20",
"paid_amount": "12.5",
"paid_usd_rate": "1",
"fee_asset": "USDT-TRC20",
"fee_amount": 0.375,
"paid_at": "2026-10-28T15:51:22.000+00:00",
"paid_anonymously": false,
"payload": "order-1042"
}
]
}
}The example shows only some of the fields. For the full list, see the Invoice type description.
Errors (code 400): PARAM_ASSET_INVALID, PARAM_FIAT_INVALID, PARAM_INVOICE_IDS_INVALID, PARAM_STATUS_INVALID, PARAM_OFFSET_INVALID, PARAM_COUNT_INVALID.
deleteInvoice
Delete an invoice. POST only. After deletion it can't be paid and no longer appears in getInvoices. A paid invoice can't be deleted.
| Parameter | Type | Description |
|---|---|---|
invoice_id | Number | Required. Invoice ID. |
Returns true.
curl https://pay.pswallet.org/api/deleteInvoice \
-H "PSWallet-Pay-API-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"invoice_id": 528}'Errors (code 400 unless stated otherwise):
PARAM_INVOICE_ID_REQUIRED,PARAM_INVOICE_ID_INVALID—invoice_idis missing or invalid.404 INVOICE_NOT_FOUND— the invoice was not found or has already been deleted.INVOICE_PAID— the invoice has already been paid.