Requests and responses
PS Wallet Pay API address, token authorization, HTTP methods, parameter and response formats, and the request rate limit.
On this page
All PS Wallet Pay API methods are called at a single address, authorized with the app token in a header, and respond with a JSON object containing the ok field.
API address
https://pay.pswallet.org/api/{method}Replace {method} with the method name, for example https://pay.pswallet.org/api/createInvoice.
- HTTPS only, UTF-8 encoding.
- The method name is case-insensitive:
getMeandgetmeare the same method.
Authorization
Pass the app token in the PSWallet-Pay-API-Token header:
PSWallet-Pay-API-Token: 1234:AbCdEf...The token looks like <app ID>:<secret>. You can view and reissue it in the app dashboard under "API token" — see the Security section for details.
A request without a token, with an invalid or reissued token, or to a deleted app will receive a 401 UNAUTHORIZED error.
HTTP methods and parameters
GETandPOSTare supported.- Parameters are passed in the query string or in the
POSTbody asapplication/jsonorapplication/x-www-form-urlencoded. - Methods that create or delete data accept only
POST. ForGETthey respond with a405 POST_REQUIREDerror.
POST-only methods:
createInvoicedeleteInvoicetransfercreateCheckdeleteCheck
The easiest approach is to always call methods via POST with a JSON body: this works for all methods, and amounts and lists are passed without escaping.
Response format
The response is always a JSON object with the ok field.
A successful response has ok: true, and the result is in the result field:
{
"ok": true,
"result": {
"app_id": 1234,
"name": "My Shop",
"payment_processing_bot_username": "pswallet"
}
}An error has ok: false, and the description is in the error field:
{
"ok": false,
"error": { "code": 400, "name": "PARAM_AMOUNT_INVALID" }
}code matches the HTTP status of the response, and name is the machine-readable error name. All codes are listed in the Errors section.
Request example
Let's create an invoice for 12.5 USDT. The payApi functions in the Node.js and Python examples can be used to call any method.
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": "Подписка на месяц"}'// Node.js 18+ (built-in fetch)
const TOKEN = process.env.PSWALLET_PAY_TOKEN;
async function payApi(method, params = {}) {
const response = await fetch(`https://pay.pswallet.org/api/${method}`, {
method: "POST",
headers: {
"PSWallet-Pay-API-Token": TOKEN,
"Content-Type": "application/json",
},
body: JSON.stringify(params),
});
const data = await response.json();
if (!data.ok) {
throw new Error(`PS Wallet Pay: ${data.error.code} ${data.error.name}`);
}
return data.result;
}
const invoice = await payApi("createInvoice", {
asset: "USDT",
amount: "12.5",
description: "Подписка на месяц",
});
console.log(invoice.bot_invoice_url);import os
import requests
TOKEN = os.environ["PSWALLET_PAY_TOKEN"]
def pay_api(method: str, params: dict | None = None):
response = requests.post(
f"https://pay.pswallet.org/api/{method}",
headers={"PSWallet-Pay-API-Token": TOKEN},
json=params or dict(),
timeout=15,
)
data = response.json()
if not data["ok"]:
error = data["error"]
raise RuntimeError(f"PS Wallet Pay: {error['code']} {error['name']}")
return data["result"]
invoice = pay_api("createInvoice", {
"asset": "USDT",
"amount": "12.5",
"description": "Подписка на месяц",
})
print(invoice["bot_invoice_url"])Rate limit
Each app is limited to 30 requests per second. If you exceed the limit, the API responds with a 429 TOO_MANY_REQUESTS error: wait a moment and retry the request.
If you need to find out about invoice payments frequently, don't poll getInvoices in a loop — set up webhooks instead.
What is checked before a method is called
Before executing a method, the API checks the request step by step and returns an error at the first problem:
| Check | Error |
|---|---|
| The method exists | 405 METHOD_NOT_FOUND |
A method that creates or deletes data is called via POST | 405 POST_REQUIRED |
| The token is provided and valid | 401 UNAUTHORIZED |
| PS Wallet Pay is currently running | 503 TEMPORARILY_UNAVAILABLE |
| The rate limit is not exceeded | 429 TOO_MANY_REQUESTS |
| The request address is on the IP allowlist (if a list is set) | 403 IP_NOT_ALLOWED |
| The app is not frozen | 403 APP_FROZEN |
After that, the method's own parameters are checked — see the sections describing the methods.
Retrying requests
Read methods (getMe, getInvoices, getBalance, and others) can be safely retried.
transferis protected from duplicate submission by thespend_idparameter. If a request was interrupted and you don't know whether the transfer went through, check it withgetTransfersusing the samespend_id— see the Transfers section for details.createInvoiceandcreateCheckhave no retry key: a repeated request will create another invoice or check. An extra unpaid invoice can be deleted withdeleteInvoice, and an unactivated check withdeleteCheck.