# API reference


Every endpoint uses `GET`, needs no authentication and answers JSON with `Cache-Control: no-store`. Token tickers contain a slash and go in the path as they are, for example `/trc20/usdt/create/`. Tickers are lowercase and case-sensitive. Amounts are decimal strings in whole asset units, never JSON numbers. Request URLs may be at most 8192 bytes. Parameters that an endpoint does not list are refused. Use HTTPS and URL-encode every query value.

Request limits apply per client IP and callback host. Errors use `{"status":"error","error":"<message>"}`; see [Errors](errors.md).

## Create and track a deposit address

### Allocate or retrieve a permanent public deposit address

`GET /{ticker}/create/`

One payout per canonical ticker and callback pair; payout and callback options are immutable. Unknown parameters are rejected. Maximum URL length is 8192 bytes.

#### Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `ticker` | path | yes | string | Lowercase registry token ticker including slash, for example trc20/usdt or bep20/usdt. The server accepts both path segments as one ticker; clients must retain the slash. Native-only tickers are not currently resolved. |
| `callback` | query | yes | string | URL-encoded public HTTPS callback URL, exactly once. Scheme and host case, trailing host dot, default port and percent-escape case are canonicalized; path and query order are preserved. |
| `address` | query | yes | string | Valid single payout address; gateway-controlled addresses are refused. |
| `pending` | query | no | string, one of `0`, `1`, default `0` | 1 also sends a detection (pending) callback in addition to the confirmed callback. |
| `post` | query | no | string, one of `0`, `1`, default `0` | 1 delivers callbacks as an application/x-www-form-urlencoded POST instead of GET. |
| `json` | query | no | string, one of `0`, `1`, default `0` | JSON POST takes precedence over form POST; otherwise GET is used. |
| `convert` | query | no | string, one of `0`, `1`, default `0` | 1 adds value_coin_convert and value_forwarded_coin_convert to confirmed callbacks. Refused with 400 when price conversion is disabled. |
| `coupon` | query | no | string | Optional fee coupon code, case insensitive. A valid code is pinned to the created address and fixes its fee for every later deposit, so a coupon that ends afterwards never changes a promised fee. Refused with 400 when the code is unknown, outside its validity window, restricted to another ticker, or past its usage limit. Ignored when the ticker and callback pair already exists, which keeps the fee that pair was promised. |

#### Example request

```bash
curl -G "https://api.suawave.com/trc20/usdt/create/" \
  --data-urlencode "callback=https://shop.example/hook?order=1001&nonce=7f3a9c" \
  --data-urlencode "address=TXyzPayoutAddressExample0000000000000"
```

#### Response `200`

Existing or newly allocated address.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string, always `success` | yes |  |
| `address_in` | string | yes | Permanent deposit address for this ticker and callback pair. |
| `address_out` | string | yes | Payout address bound to the pair. |
| `callback_url` | string | yes | Canonicalized callback URL. |
| `minimum_transaction_coin` | string | yes | Minimum deposit that is forwarded, in whole asset units. |
| `fee_percent` | string | yes | Service fee percentage pinned to this address, as a decimal string (0.50 is 0.5%). |
| `fee_fixed_coin` | string | yes | Fixed part of the service fee pinned to this address, in whole asset units. |
| `fee_network_coin` | string | yes | Network fee charged on forwarding, in whole asset units. A promotion or coupon never lowers it. |
| `fee_promotion` | string | no | Name of the promotion that produced this fee; absent when the standard fee applies. |
| `coupon` | string | no | Coupon code pinned to this address; absent when no coupon applies. |

```json
{
  "status": "success",
  "address_in": "TDepositAddressExample0000000000",
  "address_out": "TXyzPayoutAddressExample0000000000000",
  "callback_url": "https://shop.example/hook?order=1001&nonce=7f3a9c",
  "minimum_transaction_coin": "10.000000",
  "fee_percent": "0.10",
  "fee_fixed_coin": "0.100000",
  "fee_network_coin": "1.000000",
  "coupon": "LAUNCH10"
}
```

#### Errors

Statuses `400`, `429`, `503` use the standard error body described in [Errors](errors.md).

Notes for `create`:

- The canonical pair of ticker and callback identifies the order permanently. Canonicalization lowercases the scheme and host, removes a trailing host dot and a default port, and uppercases percent escapes. Path and query order are kept.
- `json=1` takes precedence over `post=1`. Without either, callbacks are delivered as `GET`.
- All options are fixed by the first call for a pair; later calls return the original options.
- Only one payout address is supported. Split payouts, caller-set confirmations, priority selection and multi-token acceptance are not available.

### Read deposit forwarding and callback history

`GET /{ticker}/logs/`

Callback is canonicalized and syntax-validated as in create, without DNS resolution. At most the 100 most recent eligible deposits are returned. Only eligible deposits to the assigned address and ticker asset are listed. Held, rejected, orphaned and below-minimum transfers are excluded. Existing orders without deposits have an empty callbacks array. Only the callback query parameter is accepted.

#### Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `ticker` | path | yes | string | Lowercase registry token ticker including slash, for example trc20/usdt or bep20/usdt. The server accepts both path segments as one ticker; clients must retain the slash. Native-only tickers are not currently resolved. |
| `callback` | query | yes | string | URL-encoded public HTTPS callback URL, exactly once. Scheme and host case, trailing host dot, default port and percent-escape case are canonicalized; path and query order are preserved. |

#### Example request

```bash
curl -G "https://api.suawave.com/trc20/usdt/logs/" \
  --data-urlencode "callback=https://shop.example/hook?order=1001&nonce=7f3a9c"
```

#### Response `200`

Read-only deposit and delivery history of the 100 most recent deposits, oldest of those first.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string, always `success` | yes |  |
| `address_in` | string | yes |  |
| `address_out` | string | yes |  |
| `callback_url` | string | yes |  |
| `notify_pending` | boolean | yes |  |
| `notify_confirmations` | integer | yes | Configured confirmations, or 1 for provider-finality policies. Does not override chain finality. |
| `priority` | string, always `default` | yes |  |
| `callbacks` | array of object | yes |  |
| `callbacks[].txid_in` | string | yes |  |
| `callbacks[].txid_out` | string | yes | Empty until forwarding confirms. |
| `callbacks[].value_coin` | string | yes | Inbound whole-asset decimal amount. |
| `callbacks[].value_forwarded_coin` | string | yes | Net amount; zero until forwarding confirms. |
| `callbacks[].confirmations` | integer | yes |  |
| `callbacks[].last_update` | string | yes | UTC transfer/settlement/delivery update timestamp. |
| `callbacks[].result` | string, one of `pending`, `sent`, `done` | yes | Deposit seen but not forwarded; forwarding confirmed but confirmed callback not acknowledged; forwarding confirmed and confirmed callback acknowledged. |
| `callbacks[].fee_percent` | string | yes | Snapshotted service fee percentage; zero without a settlement. |
| `callbacks[].fee_coin` | string | yes | Service and charged network fees; zero until forwarding confirms. |
| `callbacks[].logs` | array of object | yes | Newest first by attempt start time then ID. Only stored response excerpts are returned. |
| `callbacks[].logs[].request_url` | string | yes | Reconstructed immutable callback URL including GET fields only for GET transport. |
| `callbacks[].logs[].response_status` | integer | yes | Zero if no HTTP response. |
| `callbacks[].logs[].responses` | string | yes | At most the stored 1024-byte excerpt; invalid UTF-8 bytes are removed. |
| `callbacks[].logs[].next_try` | string or null | yes | Current delivery retry time in UTC; null for terminal delivery. Historical retry schedules are not stored. |
| `callbacks[].logs[].pending` | integer, one of `0`, `1` | yes |  |
| `callbacks[].logs[].confirmed` | integer, one of `0`, `1` | yes |  |

```json
{
  "status": "success",
  "address_in": "TDepositAddressExample0000000000",
  "address_out": "TXyzPayoutAddressExample0000000000000",
  "callback_url": "https://shop.example/hook?order=1001&nonce=7f3a9c",
  "notify_pending": true,
  "notify_confirmations": 19,
  "priority": "default",
  "callbacks": [
    {
      "txid_in": "9f2c1a0e5b7d4c3a8e6f1b2d3c4a5e6f7a8b9c0d1e2f30415263748596a7b8c9",
      "txid_out": "1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f809",
      "value_coin": "100.000000",
      "value_forwarded_coin": "98.200000",
      "confirmations": 21,
      "last_update": "2026-10-25T12:00:00Z",
      "result": "done",
      "fee_percent": "0.50",
      "fee_coin": "1.800000",
      "logs": [
        {
          "request_url": "https://shop.example/hook?order=1001&nonce=7f3a9c&address_in=TDepositAddressExample0000000000&coin=trc20_usdt&pending=0",
          "response_status": 200,
          "responses": "*ok*",
          "next_try": null,
          "pending": 0,
          "confirmed": 1
        }
      ]
    }
  ]
}
```

#### Errors

Statuses `400`, `429`, `503` use the standard error body described in [Errors](errors.md).

| Status | Meaning |
| --- | --- |
| `404` | Callback not found. |

Notes for `logs`:

| `result` | Meaning |
| --- | --- |
| `pending` | Deposit seen; forwarding has not confirmed. |
| `sent` | Forwarding confirmed; the confirmed callback has not been acknowledged yet (including exhausted retries). |
| `done` | Forwarding confirmed and the confirmed callback was acknowledged with `*ok*`. |

Entries are listed oldest first, at most the 100 most recent eligible deposits. Each entry has at most ten attempt logs, newest first. Deposits below the minimum are not listed.

## Utilities

### Get the public ticker minimum

`GET /{ticker}/info/`

No global info endpoint. Info query parameters are currently ignored.

#### Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `ticker` | path | yes | string | Lowercase registry token ticker including slash, for example trc20/usdt or bep20/usdt. The server accepts both path segments as one ticker; clients must retain the slash. Native-only tickers are not currently resolved. |

#### Example request

```bash
curl "https://api.suawave.com/trc20/usdt/info/"
```

#### Response `200`

Ticker information.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string, always `success` | yes |  |
| `coin` | string | yes | Asset symbol. |
| `ticker` | string | yes | Ticker path value. |
| `minimum_transaction_coin` | string | yes | Minimum deposit that is forwarded, in whole asset units. |
| `fee_percent` | string | yes | Service fee percentage an address created now would pay, as a decimal string (0.50 is 0.5%). Coupons are not reflected here. |
| `fee_fixed_coin` | string | yes | Fixed part of that service fee, in whole asset units. |
| `fee_network_coin` | string | yes | Network fee charged on forwarding, in whole asset units. A promotion never lowers it. |
| `fee_promotion` | string | no | Name of the active promotion; absent when the standard fee applies. |

```json
{
  "status": "success",
  "coin": "USDT",
  "ticker": "trc20/usdt",
  "minimum_transaction_coin": "10.000000",
  "fee_percent": "0.20",
  "fee_fixed_coin": "0.300000",
  "fee_network_coin": "1.000000",
  "fee_promotion": "spring sale"
}
```

#### Errors

Statuses `400`, `429`, `503` use the standard error body described in [Errors](errors.md).

### Quote the configured native forwarding fee ceiling

`GET /{ticker}/estimate/`

Returns a conservative ceiling of the forwarding fee in the chain's native coin (for example TRX or BNB), not in token units. It is a configured fee cap, not a live estimate, and has no fiat conversion. On EVM chains it caps gas cost; on resource-based chains it covers contract energy fees, while bandwidth, account activation and preparatory funding are separate. Returns 503 when no ceiling is available.

#### Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `ticker` | path | yes | string | Lowercase registry token ticker including slash, for example trc20/usdt or bep20/usdt. The server accepts both path segments as one ticker; clients must retain the slash. Native-only tickers are not currently resolved. |
| `addresses` | query | no | string, one of `1`, default `1` | Only one payout is supported. Other values and duplicate parameters are rejected. |
| `priority` | query | no | string, one of `default`, default `default` |  |

#### Example request

```bash
curl "https://api.suawave.com/trc20/usdt/estimate/"
```

#### Response `200`

Configured cap in native coin, excluding service fees. estimated_cost_currency is omitted.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string, always `success` | yes |  |
| `estimated_cost` | string | yes |  |

```json
{
  "status": "success",
  "estimated_cost": "15.000000"
}
```

#### Errors

Statuses `400`, `429`, `503` use the standard error body described in [Errors](errors.md).

> [!NOTE]
> The estimate is a conservative configured fee ceiling for the forwarding transaction, in the chain's native coin (for example TRX for `trc20/usdt`), not the amount deducted from your deposit. See [Fees and minimums](fees.md) for what is charged.

### Encode an existing public deposit address as a payment QR

`GET /{ticker}/qrcode/`

The address must be the address_in of an existing order for this ticker. Unknown, duplicate, empty and malformed parameters are rejected; maximum URL length is 8192 bytes. EVM tokens with value use an EIP-681 token transfer request with the token contract, chain ID and integer base units. Without value the payload is only the address. TRON always uses the plain address and omits the validated value, because wallet amount URI support is not assumed. Wallet support varies.

#### Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `ticker` | path | yes | string | Lowercase registry token ticker including slash, for example trc20/usdt or bep20/usdt. The server accepts both path segments as one ticker; clients must retain the slash. Native-only tickers are not currently resolved. |
| `address` | query | yes | string | Exact existing public order address_in for this ticker. |
| `value` | query | no | string | Positive decimal token units, at most asset precision and uint256 base units; no signs or exponents. TRON validates but omits it from the QR. |
| `size` | query | no | integer, default `512` | Square PNG dimensions in pixels. |

#### Example request

```bash
curl -G "https://api.suawave.com/trc20/usdt/qrcode/" \
  --data-urlencode "address=TDepositAddressExample0000000000"
```

#### Response `200`

PNG data URI and its exact encoded payment text.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string, always `success` | yes |  |
| `qr_code` | string | yes |  |
| `payment_uri` | string | yes | EIP-681 token transfer request or plain deposit address. |

```json
{
  "status": "success",
  "qr_code": "data:image/png;base64,iVBORw0KGgo...",
  "payment_uri": "TDepositAddressExample0000000000"
}
```

#### Errors

Statuses `400`, `429`, `503` use the standard error body described in [Errors](errors.md).

| Status | Meaning |
| --- | --- |
| `404` | Address not found for this ticker. |

Payment URI by network family:

| Family and request | QR payload |
| --- | --- |
| EVM token with `value` | EIP-681 token transfer request: `ethereum:<token-contract>@<chainId>/transfer?address=<address_in>&uint256=<base-units>`. Support depends on the wallet and the payer may be able to change the amount. |
| EVM token without `value` | The plain `address_in`. |
| TRON token, with or without `value` | The plain `address_in`. No interoperable TRC-20 amount URI exists, so `value` is validated but not encoded. |

The PNG is square, black on white, with a quiet zone of at least four modules. Its decoded text is exactly `payment_uri`.

### Convert an amount between fiat and priced asset currencies

`GET /convert/`

Informational CoinGecko prices cached for a short time; never used for credited, fee or payout amounts. Fiat results use 2 decimals, token results the asset's decimals, half up. A missing or stale price returns 503, never a guessed value.

#### Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `value` | query | yes | string | Positive plain decimal, at most 30 integer and 18 fraction digits. |
| `from` | query | yes | string | Fiat code or priced asset symbol, case-insensitive. |
| `to` | query | yes | string | Fiat code or priced asset symbol, case-insensitive. |

#### Example request

```bash
curl -G "https://api.suawave.com/convert/" \
  --data-urlencode "value=100" \
  --data-urlencode "from=eur" \
  --data-urlencode "to=usd"
```

#### Response `200`

Converted amount and the rate used.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string, always `success` | yes |  |
| `value_coin` | string | yes |  |
| `exchange_rate` | string | yes |  |

```json
{
  "status": "success",
  "value_coin": "108.695652",
  "exchange_rate": "1.086956521739"
}
```

#### Errors

Statuses `400`, `429`, `503` use the standard error body described in [Errors](errors.md).

### Convert an amount into the ticker's asset

`GET /{ticker}/convert/`

Same rules as /convert/ with the ticker asset as target and its registry decimals as precision.

#### Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `ticker` | path | yes | string | Lowercase registry token ticker including slash, for example trc20/usdt or bep20/usdt. The server accepts both path segments as one ticker; clients must retain the slash. Native-only tickers are not currently resolved. |
| `value` | query | yes | string | Positive plain decimal. |
| `from` | query | yes | string | Fiat code or priced asset symbol, case-insensitive. |

#### Example request

```bash
curl -G "https://api.suawave.com/trc20/usdt/convert/" \
  --data-urlencode "value=100" \
  --data-urlencode "from=usd"
```

#### Response `200`

Converted amount and the rate used.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string, always `success` | yes |  |
| `value_coin` | string | yes |  |
| `exchange_rate` | string | yes |  |

```json
{
  "status": "success",
  "value_coin": "108.695652",
  "exchange_rate": "1.086956521739"
}
```

#### Errors

Statuses `400`, `429`, `503` use the standard error body described in [Errors](errors.md).

Conversion rules, rounding and supported currencies are on the [Price conversion](conversion.md) page.

### Get the RSA callback verification key

`GET /pubkey/`

Returns the PKIX PUBLIC KEY PEM used to verify callbacks, RSA with at least 2048 bits. The x-ca-signature header of a callback is a base64 RSA-SHA256 PKCS1v15 signature over the exact full GET URL or the raw POST body. Verify using your configured external origin, preserve query ordering, deduplicate uuid and acknowledge with HTTP 200 and `*ok*` within 30 seconds. Form and JSON POST are supported. Pending and confirmed events have distinct UUIDs.

#### Example request

```bash
curl "https://api.suawave.com/pubkey/"
```

#### Response `200`

Public key only; never private key material.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string, always `success` | yes |  |
| `pubkey` | string | yes |  |

```json
{
  "status": "success",
  "pubkey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...\n-----END PUBLIC KEY-----\n"
}
```

#### Errors

Statuses `429` use the standard error body described in [Errors](errors.md).

| Status | Meaning |
| --- | --- |
| `503` | Public key unavailable. |

> [!NOTE]
> Cache the key and refresh it only when you are told about a key rotation. See [Verify callback signatures](verify-signature.md).
