API: balance, licences, withdrawals and invoices
LanaChat is paid from one prepaid balance in US dollars: licences (one per Telegram account, 30 days) and a commission on net sales are taken from it. You top it up with crypto deposits. Affiliate earnings can be withdrawn. Every billing endpoint needs an owner token: in the examples, $LANACHAT_TOKEN holds one.
Endpoints #
| Method | Path | Description | Permission | Status |
|---|---|---|---|---|
| GET | /billing/balance | The balance, this month's net sales and commission tier | owner | Planned |
| GET | /billing/ledger | Every movement: deposits, licences, commission, refunds | owner | Planned |
| GET | /billing/ledger.csv | The same ledger as CSV (from=, to=) | owner | Planned |
| GET | /billing/deposit-addresses | One deposit address per chain (with a memo on Solana) | owner | Planned |
| GET | /billing/deposits | Deposits and their confirmations | owner | Planned |
| GET | /billing/licences | Licences in stock and assigned, with days left | owner | Planned |
| POST | /billing/licences/buy | Buy licences: single or a pack of 10, 25 or 50 | owner | Planned |
| POST | /billing/licences/assign | Give a licence from stock to an account | owner | Planned |
| POST | /billing/licences/unassign | Take it back to stock with its days left | owner | Planned |
| PATCH | /billing/licences/auto-renew | Turn auto-renew on or off for an account | owner | Planned |
| GET | /billing/withdrawals | Affiliate withdrawals and their status | owner | Planned |
| POST | /billing/withdrawals | Ask for a withdrawal of affiliate earnings (from $500) | owner | Planned |
| GET | /billing/invoices | Monthly statements (year=) | owner | Planned |
| GET | /billing/invoices/{id}.pdf | One statement as PDF | owner | Planned |
| PUT | /billing/details | Company name, address and VAT number on statements | owner | Planned |
Prices in one table #
| What | Price |
|---|---|
| One licence (one Telegram account, 30 days) | $19 |
| Pack of 10 licences | $170 |
| Pack of 25 licences | $375 |
| Pack of 50 licences | $650 |
| Commission up to $30k of net sales in the month | 12% of AI sales, 4% of manual sales |
| Commission from $30k to $100k | 10% and 3% |
| Commission above $100k | 8% and 2% |
The counter is the net sales of the whole workspace in the calendar month; it resets on the 1st. Telegram Stars count at $0.013 each in net sales.
The balance object #
{
"balance_cents": 48210,
"month": "2026-10",
"net_sales_cents": 1870400,
"tier": { "up_to_cents": 3000000, "ai_rate_bp": 1200, "manual_rate_bp": 300 },
"licences": { "in_stock": 4, "assigned": 11, "expiring_7d": 2 },
"low_balance": false
}
| Field | Type | Description |
|---|---|---|
balance_cents | integer | Prepaid balance, in US cents |
month | string | The calendar month counted, YYYY-MM |
net_sales_cents | integer | Net sales of the workspace this month |
tier | object | The current tier: its ceiling up_to_cents, the AI rate and the manual rate in basis points |
licences | object | Licences in_stock, assigned, and assigned ones ending within 7 days (expiring_7d) |
low_balance | boolean | true when the balance does not cover the next 7 days of licences |
Rates are in basis points: 1200 is 12%.
The ledger entry object #
Each line of Billing › Activity in the Console.
{
"id": "led_90211",
"at": "2026-10-06T14:40:00Z",
"kind": "licences",
"label": "Licences · pack of 10",
"amount_cents": -17000,
"balance_after_cents": 31210
}
| Field | Type | Description |
|---|---|---|
id | string | The line |
at | string | ISO 8601, UTC |
kind | string | deposit, licences, commission, refund, affiliate or other |
label | string | The text of the line, as in the Console |
amount_cents | integer | Positive when money comes in, negative when it goes out |
balance_after_cents | integer | The balance after this line |
A commission line belongs to one sale: the Console shows the fan, the tier, who sent the offer (AI or manual), how the net was counted ("12,500 ★ × $0.013") and the rate.
The deposit object #
{
"id": "dep_4",
"at": "2026-10-06T13:52:00Z",
"chain": "usdt-tron",
"sent_cents": 100000,
"fee_cents": 1000,
"credited_cents": 99000,
"status": "pending",
"confirmations": "12/19"
}
| Field | Type | Description |
|---|---|---|
id | string | The deposit |
at | string | When it was seen, ISO 8601 |
chain | string | usdc-eth, usdc-sol, usdt-sol, usdt-tron or usdt-eth |
sent_cents, fee_cents, credited_cents | integer | What you sent, the fee, what lands on the balance |
status | string | pending then confirmed |
confirmations | string | Network confirmations counted, while pending |
USDC on Ethereum is credited 1:1 with no fee. Every other chain has a 1% fee: the deposit is converted to USDC (ERC20) when it arrives. The minimum is $25 per top-up.
The licence object #
{
"account_id": "acc_1001",
"creator_id": "cr_lea",
"days_left": 18,
"expires_at": "2026-10-24T09:00:00Z",
"auto_renew": true
}
| Field | Type | Description |
|---|---|---|
account_id | string | The Telegram account the licence runs on |
creator_id | string | Her creator |
days_left | integer | Days before it ends, out of 30 |
expires_at | string | When it ends |
auto_renew | boolean | Renew from stock (or buy a single) when it ends |
Licences in stock are counted, not listed one by one: each keeps its own days left (30 for a new one).
The withdrawal object #
{ "id": "wd_118", "status": "pending_review", "amount_cents": 50000, "requested_at": "2026-10-06T15:00:00Z", "tx_hash": null }
| Field | Type | Description |
|---|---|---|
id | string | The withdrawal |
status | string | pending_review, sent (with tx_hash) or rejected with a reason |
amount_cents | integer | Amount asked, at least 50000 ($500) |
requested_at | string | ISO 8601, UTC |
tx_hash | string or null | The transaction, once sent |
The invoice object #
{
"id": "LC-2026-09",
"month": "2026-09",
"licences_cents": 22800,
"commission_cents": 930000,
"total_cents": 952800,
"status": "paid",
"pdf_url": "https://api.lanachat.ai/v1/billing/invoices/LC-2026-09.pdf"
}
| Field | Type | Description |
|---|---|---|
id | string | Statement number, LC-YYYY-MM |
month | string | The month it covers |
licences_cents, commission_cents, total_cents | integer | Licences, commission and total of the month |
status | string | Paid, in progress (the current month) or failed |
pdf_url | string | The PDF of the statement |
Balance and ledger #
Get the balance #
GET /billing/balance · owner
curl https://api.lanachat.ai/v1/billing/balance \
-H "Authorization: Bearer $LANACHAT_TOKEN"
The answer is the balance object.
List the ledger #
GET /billing/ledger · owner
| Parameter | Type | Required | Description |
|---|---|---|---|
from, to | string | No | Days YYYY-MM-DD, UTC, both included |
limit, cursor | number, string | No | Pagination |
curl "https://api.lanachat.ai/v1/billing/ledger?from=2026-10-01&to=2026-10-06" \
-H "Authorization: Bearer $LANACHAT_TOKEN"
{
"data": [
{ "id": "led_90211", "at": "2026-10-06T14:40:00Z", "kind": "licences", "label": "Licences · pack of 10", "amount_cents": -17000, "balance_after_cents": 31210 },
{ "id": "led_90207", "at": "2026-10-06T13:20:00Z", "kind": "commission", "label": "Lea · Marco", "amount_cents": -468, "balance_after_cents": 48210 },
{ "id": "led_90150", "at": "2026-10-05T09:02:00Z", "kind": "deposit", "label": "Deposit · USDC on Ethereum", "amount_cents": 300000, "balance_after_cents": 48678 }
],
"next_cursor": "eyJpZCI6ImxlZF85MDE0OSJ9"
}
Export the ledger as CSV #
GET /billing/ledger.csv · owner
| Parameter | Type | Required | Description |
|---|---|---|---|
from, to | string | No | Days YYYY-MM-DD, UTC |
curl "https://api.lanachat.ai/v1/billing/ledger.csv?from=2026-09-01&to=2026-09-30" \
-H "Authorization: Bearer $LANACHAT_TOKEN" -o ledger-2026-09.csv
The same lines as Export CSV in Billing › Activity, ready for your accountant.
Deposits #
Get the deposit addresses #
GET /billing/deposit-addresses · owner
curl https://api.lanachat.ai/v1/billing/deposit-addresses \
-H "Authorization: Bearer $LANACHAT_TOKEN"
The answer gives one address per chain (Ethereum, Solana, Tron) and, for Solana, the memo.
Warning On Solana, a deposit sent without the memo cannot be matched to your workspace. Always send both the address and the memo.
You can send USDC on Ethereum (ERC20), USDC on Solana, USDT on Solana, USDT on Tron (TRC20) or USDT on Ethereum (ERC20). The network fee of your transfer is paid from your wallet.
List deposits #
GET /billing/deposits · owner
curl https://api.lanachat.ai/v1/billing/deposits \
-H "Authorization: Bearer $LANACHAT_TOKEN"
{
"data": [
{ "id": "dep_4", "at": "2026-10-06T13:52:00Z", "chain": "usdt-tron", "sent_cents": 100000, "fee_cents": 1000, "credited_cents": 99000, "status": "pending", "confirmations": "12/19" },
{ "id": "dep_3", "at": "2026-10-05T09:02:00Z", "chain": "usdc-eth", "sent_cents": 300000, "fee_cents": 0, "credited_cents": 300000, "status": "confirmed", "confirmations": null }
],
"next_cursor": null
}
The balance is credited automatically when a deposit is confirmed; it is then also a deposit line of the ledger.
Licences #
List licences #
GET /billing/licences · owner
curl https://api.lanachat.ai/v1/billing/licences \
-H "Authorization: Bearer $LANACHAT_TOKEN"
The answer gives the licences in stock and one licence object per assigned account, with its days left.
Buy licences #
POST /billing/licences/buy · owner
| Parameter | Type | Required | Description |
|---|---|---|---|
pack | integer | Yes | 1 (single, $19), 10 ($170), 25 ($375) or 50 ($650) |
qty | integer | Yes | How many of that pack |
curl -X POST https://api.lanachat.ai/v1/billing/licences/buy \
-H "Authorization: Bearer $LANACHAT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"pack": 10, "qty": 1}'
{ "licences_added": 10, "amount_cents": 17000, "balance_cents": 31210, "ledger_id": "led_90211" }
The licences go to your stock at once. A balance too low answers 402 (insufficient_balance). Licences in stock never expire, and bought licences are not refundable.
Assign a licence #
POST /billing/licences/assign · owner
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id | string | Yes | The Telegram account that gets a licence |
curl -X POST https://api.lanachat.ai/v1/billing/licences/assign \
-H "Authorization: Bearer $LANACHAT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"account_id": "acc_1001"}'
The answer is the licence object of the account. The stock licence with the fewest days left is used first: its remaining days, or 30 days if it is new. Auto-renew is on by default.
Take a licence back #
POST /billing/licences/unassign · owner
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id | string | Yes | The account that gives its licence back |
curl -X POST https://api.lanachat.ai/v1/billing/licences/unassign \
-H "Authorization: Bearer $LANACHAT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"account_id": "acc_1001"}'
The licence goes back to your stock with its days left. The AI stops replying on that account right away. To move a licence to another account, take it back, then assign it: it keeps its days, for free.
Turn auto-renew on or off #
PATCH /billing/licences/auto-renew · owner
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id | string | Yes | The account |
auto_renew | boolean | Yes | true to renew it when its days run out |
curl -X PATCH https://api.lanachat.ai/v1/billing/licences/auto-renew \
-H "Authorization: Bearer $LANACHAT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"account_id": "acc_1001", "auto_renew": false}'
When the days run out, auto-renew takes a licence from your stock first, or buys a single licence ($19) if the stock is empty. It cannot buy without balance: watch low_balance or the billing.low_balance webhook.
Affiliate withdrawals #
List withdrawals #
GET /billing/withdrawals · owner
curl https://api.lanachat.ai/v1/billing/withdrawals \
-H "Authorization: Bearer $LANACHAT_TOKEN"
A list of withdrawal objects, newest first.
Ask for a withdrawal #
POST /billing/withdrawals · owner
| Parameter | Type | Required | Description |
|---|---|---|---|
amount_cents | integer | Yes | At least 50000 ($500), at most what is available to withdraw |
curl -X POST https://api.lanachat.ai/v1/billing/withdrawals \
-H "Authorization: Bearer $LANACHAT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"amount_cents": 50000}'
{ "id": "wd_118", "status": "pending_review", "amount_cents": 50000, "requested_at": "2026-10-06T15:00:00Z", "tx_hash": null }
The earnings are sent in USDC to the wallet on file, 7 days after the month ends. Only affiliate earnings can be withdrawn, never the prepaid balance. A request under $500 is refused.
Statements #
List statements #
GET /billing/invoices · owner
| Parameter | Type | Required | Description |
|---|---|---|---|
year | integer | No | For example 2026 |
curl "https://api.lanachat.ai/v1/billing/invoices?year=2026" \
-H "Authorization: Bearer $LANACHAT_TOKEN"
One invoice object per month.
Download a statement #
GET /billing/invoices/{id}.pdf · owner
curl https://api.lanachat.ai/v1/billing/invoices/LC-2026-09.pdf \
-H "Authorization: Bearer $LANACHAT_TOKEN" -o LC-2026-09.pdf
Warning Check your statements. A billing error must be reported within 60 days of the statement that shows it; after that, the statement is final.
Set the billing details #
PUT /billing/details · owner
| Parameter | Type | Required | Description |
|---|---|---|---|
company | string | No | Company name |
email | string | No | Billing e-mail |
address, city, postal, country | string | No | Postal address |
vat | string | No | VAT number |
curl -X PUT https://api.lanachat.ai/v1/billing/details \
-H "Authorization: Bearer $LANACHAT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"company": "Mia Agency Ltd", "email": "[email protected]", "address": "12 Market Street", "city": "Dublin", "postal": "D02 X285", "country": "IE", "vat": "IE1234567T"}'
The same fields as Billing › Billing details. Statements carry these details. PUT replaces them all: a field you leave out is emptied.