# Invoices

> Creating, retrieving, and deleting payment invoices in the PS Wallet Pay API: createInvoice, getInvoices, deleteInvoice.

An invoice is a payment request that a user opens via a link and pays in PS Wallet. The payment amount minus the [fee](https://help.pswallet.org/en/pay-api/fees-and-limits) is credited to the app balance, and an `invoice_paid` [webhook](https://help.pswallet.org/en/pay-api/webhooks) 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](https://help.pswallet.org/en/pay-api/assets).

## 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](https://help.pswallet.org/en/pay-api/types#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

```bash title="cURL"
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
  }'
```

```js title="Node.js"
// 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);
```

```python title="Python"
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:

```json
{
  "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).

> [!TIP]
> 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`:

```json
{
  "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](https://help.pswallet.org/en/pay-api/assets#счета-в-долларах-и-рублях).

> [!NOTE]
> 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_type` is neither `crypto` nor `fiat`.
- `PARAM_ASSET_REQUIRED`, `PARAM_ASSET_INVALID` — the `asset` coin is missing, unknown, or currently unavailable.
- `PARAM_FIAT_REQUIRED`, `PARAM_FIAT_INVALID` — the `fiat` currency is missing or unknown.
- `PARAM_ACCEPTED_ASSETS_INVALID` — invalid `accepted_assets` list.
- `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_in` is 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. |

```bash title="cURL"
curl "https://pay.pswallet.org/api/getInvoices?status=paid&count=10" \
  -H "PSWallet-Pay-API-Token: $TOKEN"
```

Response:

```json
{
  "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](https://help.pswallet.org/en/pay-api/types#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`.

```bash title="cURL"
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_id` is 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.

---
Source: https://help.pswallet.org/en/pay-api/invoices
