# LirChain API reference

> LirChain is a crypto payments API for developers: a wallet tracker with webhooks on Bitcoin, Ethereum, Solana, Tron, BNB Chain and Polygon, a unique deposit address for every user, one-time USDT and USDC payments with a hosted payment page, and USDT and USDC payouts. It is a plain REST API with JSON, one API key header and a free plan, and it is documented in one markdown file and an OpenAPI description so that AI coding agents can integrate it without guessing.

This file is the complete reference of the LirChain merchant API, written for AI assistants and coding agents. The same reference for people is at https://lirchain.com/docs and the OpenAPI description is at https://lirchain.com/openapi.json.

## Overview

An account is organised in projects. A project belongs to one service (`deposit_wallets`, `one_time_payments`, `wallet_tracker` or `payouts`) and has its own API key. The key decides what a request works on: it can only use the endpoints of its project's service and only sees that project's data. A new account starts on the Free plan with one project for every service.

- Base URL: `https://api.lirchain.com`
- Authentication: send the project's API key in the `x-api-key` header of every request. A key is made in the dashboard (https://lirchain.com/dashboard): open the project and press "Refresh API key". It is shown once. Keep it on the server, never in a browser or an app.
- `POST` requests take a JSON body with the `content-type: application/json` header. `GET` and `DELETE` requests take their values in the query.
- Lists come in pages of 50, asked for with `?page=`, and have the shape `{ "items": [...], "page": 1, "total_pages": 3 }`.
- Ids are UUIDs. Times ending in `_ms` are milliseconds since 1970.
- `external_id` is your own id for a payment, wallet, tracker or payout (a user id, an order id), up to 255 characters. It is stored, returned wherever the object is returned and sent in its webhooks. It is `null` when none was sent.

## Integration recipes

- Credit users for deposits: create a Deposit Wallets project, call "Create a wallet" once per user with the user's id as `external_id`, show the returned `address` (or the hosted page https://lirchain.com/deposit/<wallet id>), and credit the user `receive_amount` when the `deposit-wallet` webhook arrives.
- Take a payment for an order: create a One-Time Payments project, call "Create a payment" with the price in dollars and the order id as `external_id`, send the customer to https://lirchain.com/pay/<payment id> (or show `address` and `pay_amount`), and fulfil the order when the `one-time-payment` webhook arrives with `status` `paid`.
- Watch a wallet: create a Wallet Tracker project, call "Create a tracker" with the network and the address, and handle the `wallet-tracker` webhook for every transfer to or from it.
- Pay a user: create a Payouts project and call "Create a payout" with the network, USDT or USDC, the address and the amount. Read the payout to follow its status.
- In a webhook handler, answer 2xx quickly, ignore an `x-webhook-id` already handled, and read the payment or deposit from the API before acting on it.

## Code in other languages

Every endpoint works the same way, so one function per language is enough as a model. This is "Create a wallet" (`POST /merchant/deposit-wallet/create`):

JavaScript:

```javascript
const API_KEY = "YOUR_API_KEY";

async function createDepositWallet(params) {
    const response = await fetch("https://api.lirchain.com/merchant/deposit-wallet/create", {
        method: "POST",
        headers: { "x-api-key": API_KEY, "content-type": "application/json" },
        body: JSON.stringify(params),
    });

    if (!response.ok) {
        throw new Error(`LirChain API ${response.status}: ${await response.text()}`);
    }

    return response.json();
}

const result = await createDepositWallet({
    network: "polygon",
    asset: "USDC",
    external_id: "customer-7731",
});
```

TypeScript:

```typescript
const API_KEY = "YOUR_API_KEY";

type CreateDepositWalletParams = {
    network: string;
    asset: string;
    external_id?: string;
};

type CreateDepositWalletResult = {
    id: string;
    project_id: string;
    merchant_id: string;
    network: string;
    address: string;
    asset: string;
    external_id: string | null;
};

async function createDepositWallet(params: CreateDepositWalletParams): Promise<CreateDepositWalletResult> {
    const response = await fetch("https://api.lirchain.com/merchant/deposit-wallet/create", {
        method: "POST",
        headers: { "x-api-key": API_KEY, "content-type": "application/json" },
        body: JSON.stringify(params),
    });

    if (!response.ok) {
        throw new Error(`LirChain API ${response.status}: ${await response.text()}`);
    }

    return response.json();
}

const result = await createDepositWallet({
    network: "polygon",
    asset: "USDC",
    external_id: "customer-7731",
});
```

Python:

```python
import requests

API_KEY = "YOUR_API_KEY"


def create_deposit_wallet(**params):
    response = requests.post(
        "https://api.lirchain.com/merchant/deposit-wallet/create",
        headers={"x-api-key": API_KEY},
        json=params,
        timeout=30,
    )
    response.raise_for_status()
    return response.json()


result = create_deposit_wallet(
    network="polygon",
    asset="USDC",
    external_id="customer-7731",
)
```

PHP:

```php
<?php

const API_KEY = "YOUR_API_KEY";

function create_deposit_wallet(array $params): array
{
    $curl = curl_init("https://api.lirchain.com/merchant/deposit-wallet/create");

    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($params),
        CURLOPT_HTTPHEADER => ["x-api-key: " . API_KEY, "content-type: application/json"],
    ]);

    $body = curl_exec($curl);
    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

    if ($body === false || $status >= 400) {
        throw new Exception("LirChain API $status: $body");
    }

    return json_decode($body, true);
}

$result = create_deposit_wallet([
    "network" => "polygon",
    "asset" => "USDC",
    "external_id" => "customer-7731",
]);
```

Go:

```go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const apiKey = "YOUR_API_KEY"

func CreateDepositWallet(params map[string]any) (map[string]any, error) {
	body, err := json.Marshal(params)
	if err != nil {
		return nil, err
	}

	request, err := http.NewRequest("POST", "https://api.lirchain.com/merchant/deposit-wallet/create", bytes.NewReader(body))
	if err != nil {
		return nil, err
	}
	request.Header.Set("x-api-key", apiKey)
	request.Header.Set("content-type", "application/json")

	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	data, err := io.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	if response.StatusCode >= 400 {
		return nil, fmt.Errorf("LirChain API %d: %s", response.StatusCode, data)
	}

	var result map[string]any
	return result, json.Unmarshal(data, &result)
}

func main() {
	result, err := CreateDepositWallet(map[string]any{
		"network": "polygon",
		"asset": "USDC",
		"external_id": "customer-7731",
	})
	fmt.Println(result, err)
}
```

For a `GET` or `DELETE` endpoint the values go in the query string instead of the body. The docs page has every endpoint in every language.

## Networks and assets

Deposit wallets, one-time payments and payouts work on Ethereum, BNB Chain and Polygon. The wallet tracker also reads Tron, Solana and Bitcoin. Send `asset` as the symbol, or as the contract address for a token, in any letter case. USDT and USDC are dollars one to one. A network's own coin (ETH, BNB, POL) can be sent to a deposit wallet only: it is exchanged into dollars when it arrives. One-time payments and payouts are in USDT and USDC only. In answers, `asset` is the symbol and `contract` is the token's contract address on that network.

| network | Asset | Contract | Services |
| --- | --- | --- | --- |
| `ethereum` | USDT | `0xdac17f958d2ee523a2206206994597c13d831ec7` | all |
| `ethereum` | USDC | `0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48` | all |
| `ethereum` | ETH | the network's own coin | all |
| `bsc` | USDT | `0x55d398326f99059ff775485246999027b3197955` | all |
| `bsc` | USDC | `0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d` | all |
| `bsc` | BNB | the network's own coin | all |
| `polygon` | USDT | `0xc2132d05d31c914a87c6611c10748aeb04b58e8f` | all |
| `polygon` | USDC | `0x3c499c542cef5e3811e1192ce70d8cc03d5c3359` | all |
| `polygon` | POL | the network's own coin | all |
| `bitcoin` | BTC | the network's own coin | wallet tracker only |
| `solana` | USDT | `Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB` | wallet tracker only |
| `solana` | USDC | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` | wallet tracker only |
| `solana` | SOL | the network's own coin | wallet tracker only |
| `tron` | USDT | `TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t` | wallet tracker only |
| `tron` | USDC | `TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8` | wallet tracker only |
| `tron` | TRX | the network's own coin | wallet tracker only |

A transfer is counted once it is 12 blocks deep on Ethereum, BNB Chain and Polygon.

## Fees and balance

A merchant has one balance, in dollars. Every deposit to a deposit wallet and every transfer to a one-time payment is added to it once confirmed. The plan, the fees, payouts and withdrawals are taken from it. Withdrawals are made in the dashboard, as USDT or USDC on a chosen network.

Every operation (a deposit to a deposit wallet, a transfer to a one-time payment, a payout, a withdrawal) costs a percentage of its amount set by the plan, never less than $0.10. For money coming in, the amount is added to the balance and the fee is taken from it. For a payout or a withdrawal the fee is taken on top of the amount. Wallet tracker events have no fee, and creating wallets, payments and trackers is free.

A deposit in a network's own coin is exchanged into USDT on that network's main exchange (which keeps about 0.3%) before it is added to the balance. A deposit worth less than $1 does not count. A one-time payment and a payout must be for at least $1.

Plans:

- Free: free, 1% per operation, 15 deposit wallets, 100 one-time payments per 30 days, 5 tracked wallets, 30 tracker events per 30 days, unlimited payouts
- Starter: $19.99 per month, 0.5% per operation, 1,000 deposit wallets, 10,000 one-time payments per 30 days, 1,000 tracked wallets, 10,000 tracker events per 30 days, unlimited payouts
- Business: $49.99 per month, 0.375% per operation, 20,000 deposit wallets, 200,000 one-time payments per 30 days, 20,000 tracked wallets, 200,000 tracker events per 30 days, unlimited payouts
- Enterprise: $249.99 per month, 0.25% per operation, 1,000,000 deposit wallets, 10,000,000 one-time payments per 30 days, 1,000,000 tracked wallets, 10,000,000 tracker events per 30 days, unlimited payouts

## Errors

A request that fails answers with a status code and a JSON body with one field, `message`.

- `400`: The request is not valid: a field is missing, an id is not an id, or the network and asset are not supported.
- `401`: The API key header is missing.
- `402`: Your balance is too low for the payout and its fee.
- `403`: The key is unknown, belongs to a project of another service, or the plan does not allow it (no active plan, or a limit is reached).
- `404`: The path does not exist, or the project has nothing with that id.
- `429`: Too many requests. The retry-after header says how many seconds to wait.
- `500`: Something went wrong on our side.
- `503`: Wallets cannot be created right now. Try again later.

## Rate limits

Every project can make 300 read requests (GET) and 60 write requests (POST, DELETE) per minute. The `x-ratelimit-remaining` header of every answer says how many are left. Past the limit the answer is `429` with a `retry-after` header in seconds.

## Webhooks

Set a webhook URL (https only) in the project's settings in the dashboard. A `POST` request with a JSON body is sent to it when something happens in the project. Answer with a 2xx status within 10 seconds. Anything else counts as a failure and the same event is sent again after a minute, up to 20 times. Every try of one event carries the same `x-webhook-id` header. Webhooks are not signed: treat one as a hint and read the payment or deposit from the API before acting on it.

- `deposit-wallet`: A deposit to one of the project's deposit wallets was added to your balance.
- `one-time-payment`: A one-time payment of the project became paid.
- `wallet-tracker`: A tracked wallet of the project sent or received a transfer.

Deposit to a deposit wallet:

```json
{
  "type": "deposit-wallet",
  "deposit": {
    "id": "41b0d4fe-8b49-4623-bd8f-6f04586b06c9",
    "wallet_id": "3f4911a7-2c26-4f9c-a97c-80b25b6feb8c",
    "external_id": "customer-7731",
    "project_id": "3d6b1130-da92-4ddf-bad2-93f898993c39",
    "network": "ethereum",
    "asset": "USDT",
    "contract": "0xdac17f958d2ee523a2206206994597c13d831ec7",
    "amount": "250.5",
    "pay_amount": "250.5",
    "fee": "1.2525",
    "receive_amount": "249.2475",
    "created_ms": 1791503990112
  }
}
```

One-time payment paid:

```json
{
  "type": "one-time-payment",
  "payment": {
    "id": "ccf1c790-9d3d-4cda-98a9-5cd590a102df",
    "external_id": "order-1042",
    "project_id": "3d6b1130-da92-4ddf-bad2-93f898993c39",
    "network": "polygon",
    "address": "0x20d5b8802fc43b24cdbc9cdaa59dd6690626ad2c",
    "asset": "USDT",
    "contract": "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
    "amount": 49.5,
    "pay_amount": 49.5,
    "receive_amount": "49.2525",
    "received": "49.5",
    "status": "paid",
    "fee": "0.2475",
    "created_ms": 1791503932667,
    "expire_ms": 1791507532667
  }
}
```

Transfer of a tracked wallet:

```json
{
  "type": "wallet-tracker",
  "event": {
    "id": "95e04e32-5c98-4f68-8c62-f487bda0ed5c",
    "tracker_id": "67153a22-af19-4352-ab8e-041006c76c7b",
    "external_id": "treasury",
    "project_id": "ea54aa6c-21d7-46a4-b1fe-c0703f74a2af",
    "created_ms": 1791504120904
  },
  "transfer": {
    "network": "ethereum",
    "block_number": 26151012,
    "tx_hash": "0x4e3a…9f21",
    "log_index": "28",
    "from_address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
    "to_address": "0x52ae0f1c8d4b7a90e3b6c2d15f8a47e09b3c91f3",
    "asset": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
    "amount": "102870865",
    "symbol": "USDC",
    "amount_units": "102.870865"
  }
}
```

## Hosted pages

Every one-time payment and every deposit wallet has a ready-made page for the customer, made from the `id` returned when it is created. They need no login.

- Payment: `https://lirchain.com/pay/<payment id>` shows the amount, the address with a QR code, the network and the time left, and updates by itself.
- Deposit wallet: `https://lirchain.com/deposit/<wallet id>` shows the address with a QR code and the latest deposits.

## General

Works with the API key of any project. Works with the API key of any project.

### Check an API key

`GET /merchant/ping`

Answers when the key is valid and tells you which project and service it belongs to.

Request:

```bash
curl "https://api.lirchain.com/merchant/ping" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "status": "ok",
  "project_id": "3d6b1130-da92-4ddf-bad2-93f898993c39",
  "service": "one_time_payments"
}
```

### Get your plan's limits

`GET /merchant/allowance`

How much of every limit of your plan is used and how much it allows.

Request:

```bash
curl "https://api.lirchain.com/merchant/allowance" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "projects": { "used": 4, "limit": 4 },
  "deposit_wallets": { "used": 12, "limit": 1000 },
  "one_time_payments": { "used": 310, "limit": 1000 },
  "wallet_trackers": { "used": 3, "limit": 1000 },
  "tracker_events": { "used": 542, "limit": 1000 }
}
```

Notes:

- The limits belong to your account and are shared by all its projects, so every key gives the same answer.
- projects, deposit_wallets and wallet_trackers count what exists now. The others count what happened since your plan's current period started.
- Without an active plan the answer is 403.

## One-Time Payments

Needs the API key of a project of the service `one_time_payments`. A payment request for one purchase, paid in USDT or USDC. Every payment gets its own address. It is pending until one transfer brings at least the amount to that address, then it is paid. Smaller transfers are not added up: they are added to your balance, but they do not pay the payment.

### Create a payment

`POST /merchant/one-time-payment/create`

Creates a pending payment and the address your customer pays to.

JSON body:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `network` | string | yes | ethereum, bsc or polygon. |
| `asset` | string | yes | What it is paid in: USDT or USDC, by its symbol or its contract address. |
| `amount` | number | no | What the customer pays, in dollars, at least 1. You receive it minus the fee. Give this or receive_amount. |
| `receive_amount` | number | no | What you want to receive after the fee, in dollars. The customer pays that plus the fee, rounded up to a cent. Give this or amount. |
| `external_id` | string | no | Your own id for the payment, e.g. your order id, up to 255 characters. We store it and give it back, also in webhooks. |

Request:

```bash
curl https://api.lirchain.com/merchant/one-time-payment/create \
  -H "x-api-key: YOUR_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "network": "polygon",
    "asset": "USDT",
    "amount": 49.5,
    "external_id": "order-1042"
  }'
```

Response (201):

```json
{
  "id": "ccf1c790-9d3d-4cda-98a9-5cd590a102df",
  "external_id": "order-1042",
  "network": "polygon",
  "address": "0x20d5b8802fc43b24cdbc9cdaa59dd6690626ad2c",
  "asset": "USDT",
  "amount": 49.5,
  "pay_amount": 49.5,
  "receive_amount": "49.2525",
  "status": "pending",
  "fee": "0",
  "created_ms": 1791503932667,
  "expire_ms": 1791507532667
}
```

Notes:

- Counts towards the payments of your billing period. When the limit is reached the answer is 403.
- Creating a payment is free. The fee is charged when it is paid.
- expire_ms is one hour after created_ms: the time you should give your customer to pay.
- amount is the price in dollars, and also how many of the stablecoin the customer has to send in one transfer. pay_amount is the same number: what is to be paid.
- receive_amount is what you receive on your balance for the payment: what is paid minus the fee. While the payment is pending it is worked out with the fee of your plan as it is now. Once it is paid it is what you did receive.

### Get a payment

`GET /merchant/one-time-payment/otp`

One payment of the project, with its current status.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | yes | The id of the payment. |

Request:

```bash
curl "https://api.lirchain.com/merchant/one-time-payment/otp?id=ccf1c790-9d3d-4cda-98a9-5cd590a102df" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "id": "ccf1c790-9d3d-4cda-98a9-5cd590a102df",
  "external_id": "order-1042",
  "network": "polygon",
  "address": "0x20d5b8802fc43b24cdbc9cdaa59dd6690626ad2c",
  "asset": "USDT",
  "amount": 49.5,
  "pay_amount": 49.5,
  "receive_amount": "49.2525",
  "status": "paid",
  "fee": "0.2475",
  "created_ms": 1791503932667,
  "expire_ms": 1791507532667
}
```

Notes:

- status is pending or paid.
- fee is what we charged for the transfer that paid the payment: the percentage of your plan. It is 0 until the payment is paid.

### List payments

`GET /merchant/one-time-payment/page`

The payments of the project, newest first.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | number | no | The page to return, starting at 1. 50 items per page. |

Request:

```bash
curl "https://api.lirchain.com/merchant/one-time-payment/page?page=1" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "items": [
    {
      "id": "ccf1c790-9d3d-4cda-98a9-5cd590a102df",
      "external_id": "order-1042",
      "network": "polygon",
      "address": "0x20d5b8802fc43b24cdbc9cdaa59dd6690626ad2c",
      "asset": "USDT",
      "amount": 49.5,
      "pay_amount": 49.5,
      "receive_amount": "49.2525",
      "status": "paid",
      "fee": "0.2475",
      "created_ms": 1791503932667,
      "expire_ms": 1791507532667
    }
  ],
  "page": 1,
  "total_pages": 1
}
```

## Deposit Wallets

Needs the API key of a project of the service `deposit_wallets`. A permanent address for one customer. Every transfer of the wallet's asset to it becomes a deposit of the project.

### Create a wallet

`POST /merchant/deposit-wallet/create`

Creates a wallet with a new address. It accepts one asset on one network.

JSON body:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `network` | string | yes | ethereum, bsc or polygon. |
| `asset` | string | yes | What it is paid in: a token by its symbol (USDT, USDC) or contract address, or the network's own coin by its symbol (ETH, BNB, POL). |
| `external_id` | string | no | Your own id for the wallet, e.g. the id of the customer it belongs to, up to 255 characters. We store it and give it back, also in webhooks. |

Request:

```bash
curl https://api.lirchain.com/merchant/deposit-wallet/create \
  -H "x-api-key: YOUR_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "network": "polygon",
    "asset": "USDC",
    "external_id": "customer-7731"
  }'
```

Response (201):

```json
{
  "id": "3f4911a7-2c26-4f9c-a97c-80b25b6feb8c",
  "project_id": "3d6b1130-da92-4ddf-bad2-93f898993c39",
  "merchant_id": "7c551c17-1a48-4e2b-b3ac-7ad389a753c6",
  "network": "polygon",
  "address": "0x748aaf6d861698dc3c4ee2fca3c27ba13edc7891",
  "asset": "USDC",
  "external_id": "customer-7731"
}
```

Notes:

- Counts towards the wallets of your plan. When the limit is reached the answer is 403.

### Delete a wallet

`DELETE /merchant/deposit-wallet/delete`

Deletes the wallet and frees its place in your plan. Deposits sent to its address afterwards are not recorded.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `wallet_id` | uuid | yes | The id of the wallet. |

Request:

```bash
curl -X DELETE "https://api.lirchain.com/merchant/deposit-wallet/delete?wallet_id=3f4911a7-2c26-4f9c-a97c-80b25b6feb8c" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (204):

```json
(no body)
```

### List wallets

`GET /merchant/deposit-wallet/wallets`

The wallets of the project.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | number | no | The page to return, starting at 1. 50 items per page. |

Request:

```bash
curl "https://api.lirchain.com/merchant/deposit-wallet/wallets?page=1" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "items": [
    {
      "id": "3f4911a7-2c26-4f9c-a97c-80b25b6feb8c",
      "project_id": "3d6b1130-da92-4ddf-bad2-93f898993c39",
      "merchant_id": "7c551c17-1a48-4e2b-b3ac-7ad389a753c6",
      "network": "polygon",
      "address": "0x748aaf6d861698dc3c4ee2fca3c27ba13edc7891",
      "asset": "USDC",
      "external_id": "customer-7731"
    }
  ],
  "page": 1,
  "total_pages": 1
}
```

### List deposits

`GET /merchant/deposit-wallet/deposits`

The deposits of the project, newest first.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | number | no | The page to return, starting at 1. 50 items per page. |
| `wallet_id` | uuid | no | Only the deposits of this wallet. |

Request:

```bash
curl "https://api.lirchain.com/merchant/deposit-wallet/deposits?page=1&wallet_id=3f4911a7-2c26-4f9c-a97c-80b25b6feb8c" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "items": [
    {
      "id": "41b0d4fe-8b49-4623-bd8f-6f04586b06c9",
      "wallet_id": "3f4911a7-2c26-4f9c-a97c-80b25b6feb8c",
      "project_id": "3d6b1130-da92-4ddf-bad2-93f898993c39",
      "merchant_id": "7c551c17-1a48-4e2b-b3ac-7ad389a753c6",
      "transfer_id": "41b0d4fe-8b49-4623-bd8f-6f04586b06c9",
      "amount": "250.5",
      "pay_amount": "250.5",
      "fee": "1.2525",
      "receive_amount": "249.2475",
      "created_ms": 1791503990112,
      "processed_ms": 1791503991340
    }
  ],
  "page": 1,
  "total_pages": 1
}
```

Notes:

- amount is in whole units of the wallet's asset, as text so no precision is lost.
- transfer_id is our id of the transfer on the chain this deposit is. It is the same as id: one transfer is only ever one deposit.
- amount is what arrived, in the wallet's asset. pay_amount is what was paid in dollars: the same number for USDT and USDC, and for a network's own coin what it was exchanged for. fee is our fee, and receive_amount is what you receive on your balance: pay_amount without the fee. All three are 0 while processed_ms is null: the deposit was seen but is not on your balance yet, which for a coin takes until its exchange is confirmed.

## Wallet Tracker

Needs the API key of a project of the service `wallet_tracker`. Follows any address, on more networks than the other services: Ethereum, BNB Chain, Polygon, Tron, Solana and Bitcoin. Every transfer of USDT, USDC or the network's own coin to or from it becomes an event of the project.

### Create a tracker

`POST /merchant/wallet-tracker/create`

Starts tracking an address on one network.

JSON body:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `network` | string | yes | ethereum, bsc, polygon, tron, solana or bitcoin. |
| `address` | string | yes | The address to track, written the way that network writes addresses: 0x and 40 hex characters, T… on Tron, a base58 address on Solana, 1…, 3… or bc1… on Bitcoin. |
| `external_id` | string | no | Your own id for the tracker, up to 255 characters. We store it and give it back, also in webhooks. |

Request:

```bash
curl https://api.lirchain.com/merchant/wallet-tracker/create \
  -H "x-api-key: YOUR_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "network": "ethereum",
    "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
    "external_id": "treasury"
  }'
```

Response (201):

```json
{
  "id": "67153a22-af19-4352-ab8e-041006c76c7b",
  "project_id": "ea54aa6c-21d7-46a4-b1fe-c0703f74a2af",
  "merchant_id": "7c551c17-1a48-4e2b-b3ac-7ad389a753c6",
  "network": "ethereum",
  "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
  "external_id": "treasury"
}
```

Notes:

- Counts towards the trackers of your plan. When the limit is reached the answer is 403.
- An address that is not a valid one for the network is refused with 400. Ethereum, BNB Chain and Polygon addresses are stored and returned in lowercase. The others are kept exactly as written: their capitals matter.
- A tracker reports what happens from the moment it is added, not what happened before.

### Delete a tracker

`DELETE /merchant/wallet-tracker/delete`

Stops tracking the address and frees its place in your plan.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | yes | The id of the tracker. |

Request:

```bash
curl -X DELETE "https://api.lirchain.com/merchant/wallet-tracker/delete?id=67153a22-af19-4352-ab8e-041006c76c7b" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (204):

```json
(no body)
```

### List trackers

`GET /merchant/wallet-tracker/trackers`

The trackers of the project.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | number | no | The page to return, starting at 1. 50 items per page. |

Request:

```bash
curl "https://api.lirchain.com/merchant/wallet-tracker/trackers?page=1" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "items": [
    {
      "id": "67153a22-af19-4352-ab8e-041006c76c7b",
      "project_id": "ea54aa6c-21d7-46a4-b1fe-c0703f74a2af",
      "merchant_id": "7c551c17-1a48-4e2b-b3ac-7ad389a753c6",
      "network": "ethereum",
      "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
      "external_id": "treasury"
    }
  ],
  "page": 1,
  "total_pages": 1
}
```

### List events

`GET /merchant/wallet-tracker/events`

The events of the project with their transfers, newest first.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | number | no | The page to return, starting at 1. 50 items per page. |
| `wallet_tracker_id` | uuid | no | Only the events of this tracker. |

Request:

```bash
curl "https://api.lirchain.com/merchant/wallet-tracker/events?page=1&wallet_tracker_id=67153a22-af19-4352-ab8e-041006c76c7b" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "items": [
    {
      "id": "95e04e32-5c98-4f68-8c62-f487bda0ed5c",
      "tracker_id": "67153a22-af19-4352-ab8e-041006c76c7b",
      "created_ms": 1791504120904,
      "transfer": {
        "network": "ethereum",
        "block_number": 26151012,
        "tx_hash": "0x4e3a…9f21",
        "log_index": "28",
        "from_address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
        "to_address": "0x52ae0f1c8d4b7a90e3b6c2d15f8a47e09b3c91f3",
        "asset": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
        "amount": "102870865",
        "symbol": "USDC",
        "amount_units": "102.870865"
      }
    }
  ],
  "page": 1,
  "total_pages": 1
}
```

Notes:

- asset and amount are the chain's own values: the token's contract address and the amount in its smallest unit. The network's own coin has the address 0x0000000000000000000000000000000000000000 and no log_index.
- symbol and amount_units are the same transfer in readable form.
- The tracked address is the sender when it equals from_address and the receiver when it equals to_address.
- On Bitcoin and Solana one transaction can have many senders and receivers, so an event is what the transaction changed for your address: the amount it received minus what it spent, or the other way round. The other side is an empty string. On Solana the network fee your address paid is not counted.
- asset is written the way the network writes it: a T… contract on Tron, the token's mint on Solana. On Solana log_index holds the mint for a token event.
- A transfer that failed on its chain is never reported.
- Solana addresses are read about every 20 seconds, and only the usual token account of an address is watched for USDT and USDC.

## Payouts

Needs the API key of a project of the service `payouts`. Money from your balance to an address you choose, for example to pay one of your users. The amount and the fee are taken from your balance the moment the payout is created, and a payout cannot be cancelled: once it is created it is sent.

### Create a payout

`POST /merchant/payout/create`

Takes the amount and the fee from your balance and creates the payout to the address. This cannot be undone.

JSON body:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `network` | string | yes | ethereum, bsc or polygon. |
| `asset` | string | yes | The token: its symbol (USDT, USDC) or its contract address. |
| `address` | string | yes | Where the money goes: 0x followed by 40 hex characters. |
| `amount` | number or string | yes | The amount in dollars, at least 1, with at most two decimals. |
| `external_id` | string | no | Your own id for the payout, e.g. the id of the user you are paying, up to 255 characters. We store it and give it back. |

Request:

```bash
curl https://api.lirchain.com/merchant/payout/create \
  -H "x-api-key: YOUR_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "network": "polygon",
    "asset": "USDT",
    "address": "0x52aE0F1c8D4b7A90e3B6c2D15f8A47e09B3C91F3",
    "amount": "25.50",
    "external_id": "user-5521"
  }'
```

Response (201):

```json
{
  "id": "8a1f4c2e-6d3b-4f70-9c15-2e7b0a94d6c3",
  "external_id": "user-5521",
  "network": "polygon",
  "asset": "USDT",
  "address": "0x52ae0f1c8d4b7a90e3b6c2d15f8a47e09b3c91f3",
  "amount": "25.50",
  "fee": "0.1275",
  "receive_amount": "25.50",
  "pay_amount": "25.6275",
  "status": "pending",
  "tx_hash": null,
  "created_ms": 1791506100412,
  "processed_ms": null
}
```

Notes:

- The fee is the percentage of your plan, taken from your balance on top of the amount. receive_amount is what the receiver gets (the amount), pay_amount is what leaves your balance for it (the amount and the fee).
- Your balance must cover the amount and the fee, otherwise the answer is 402 and nothing is taken.
- status is pending, processing, completed or failed. tx_hash is set once the payout is completed. A failed payout was not sent, and its amount and fee are back on your balance.
- A payout is sent within a few seconds of being created (processing) and becomes completed once the network has safely confirmed it, 12 blocks later. There is no webhook for payouts yet: read the payout to see its status.

### Get a payout

`GET /merchant/payout/payout`

One payout of the project, with its current status.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | yes | The id of the payout. |

Request:

```bash
curl "https://api.lirchain.com/merchant/payout/payout?id=8a1f4c2e-6d3b-4f70-9c15-2e7b0a94d6c3" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "id": "8a1f4c2e-6d3b-4f70-9c15-2e7b0a94d6c3",
  "external_id": "user-5521",
  "network": "polygon",
  "asset": "USDT",
  "address": "0x52ae0f1c8d4b7a90e3b6c2d15f8a47e09b3c91f3",
  "amount": "25.50",
  "fee": "0.1275",
  "receive_amount": "25.50",
  "pay_amount": "25.6275",
  "status": "pending",
  "tx_hash": null,
  "created_ms": 1791506100412,
  "processed_ms": null
}
```

### List payouts

`GET /merchant/payout/page`

The payouts of the project, newest first.

Query:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | number | no | The page to return, starting at 1. 50 items per page. |

Request:

```bash
curl "https://api.lirchain.com/merchant/payout/page?page=1" \
  -H "x-api-key: YOUR_API_KEY"
```

Response (200):

```json
{
  "items": [
    {
      "id": "8a1f4c2e-6d3b-4f70-9c15-2e7b0a94d6c3",
      "external_id": "user-5521",
      "network": "polygon",
      "asset": "USDT",
      "address": "0x52ae0f1c8d4b7a90e3b6c2d15f8a47e09b3c91f3",
      "amount": "25.50",
      "fee": "0.1275",
      "receive_amount": "25.50",
      "pay_amount": "25.6275",
      "status": "pending",
      "tx_hash": null,
      "created_ms": 1791506100412,
      "processed_ms": null
    }
  ],
  "page": 1,
  "total_pages": 1
}
```

