# API: Telegram accounts, pools and stories

_API · 8 min read · Updated 2026-10-22 · https://lanachat.ai/guides/api-telegram-accounts/_

A **Telegram account** is one account of a creator, connected to LanaChat through a business connection (a bot she adds in her Telegram settings). Accounts are grouped in **pools**: a pool is one creator, one market and one traffic source, and new conversations from a tracking link are spread across the sending accounts of the right pool. **Stories** are posted on one or more accounts at once.

## Endpoints

| Method | Path | Description | Permission | Status |
|---|---|---|---|---|
| GET | `/accounts` | List accounts (`creator_id=`, `health=connected,pending,expired`) | `can_setup` | Planned |
| POST | `/accounts` | Add an account with its bot token; checked with Telegram before it is saved | `can_setup` | Planned |
| GET | `/accounts/{id}` | One account, its health and its load this hour | `can_setup` | Planned |
| PATCH | `/accounts/{id}` | Change its brain, market, traffic, alias or reply language; turn it on or off | `can_setup` | Planned |
| DELETE | `/accounts/{id}` | Disconnect the account (its conversations are kept) | `can_setup` | Planned |
| POST | `/accounts/{id}/check` | Test the connection now instead of waiting for the hourly check | `can_setup` | Planned |
| GET | `/pools` | Every pool with its accounts, capacity and status | `can_tracking` | Planned |
| GET | `/pools/settings` | Hourly cap of the workspace and the distribution rules | `can_tracking` | Planned |
| PUT | `/pools/settings` | Change the hourly cap (100 to 100,000) and the distribution | `can_tracking` | Planned |
| PATCH | `/pools/accounts/{account_id}` | Take an account in or out of the pool, pause it, set its weight or hourly limit | `can_tracking` | Planned |
| GET | `/pools/events` | The pool log: flood waits, pauses, resumes, links held | `can_tracking` | Planned |
| GET | `/stories` | Posted and scheduled stories (`creator_id=`, `status=`) | `can_setup` | Planned |
| POST | `/stories` | Post a story now or schedule it on one or more accounts | `can_setup` | Planned |
| GET | `/stories/{id}` | One story with its views, reactions and link clicks | `can_setup` | Planned |
| DELETE | `/stories/{id}` | Cancel a scheduled story | `can_setup` | Planned |

## The account object

```json
{
  "id": "acc_1001",
  "creator_id": "cr_lea",
  "username": "lea_officiel",
  "bot_username": "lea_helper_bot",
  "health": "connected",
  "active": true,
  "brain_id": "br_lea_main",
  "pool_id": "pool_lea_fr_instagram",
  "market": "fr",
  "traffic": "instagram",
  "story_rights": true,
  "last_activity_at": "2026-10-06T13:58:20Z"
}
```

| Field | Type | Description |
|---|---|---|
| `id` | string | Starts with `acc_` |
| `creator_id` | string | The creator this account belongs to |
| `username` | string | The Telegram @username of the account, without the @ |
| `bot_username` | string | The bot linked through the business connection |
| `health` | string | `connected`, `pending` or `expired` |
| `active` | boolean | `false` when the account is turned off: the AI does not answer on it |
| `brain_id` | string or null | The AI Brain that answers on this account |
| `pool_id` | string | The pool its `market` and `traffic` tags put it in |
| `market` | string | Language market, for example `fr`, `en`, `pt-BR`, or `all` |
| `traffic` | string | Traffic source, for example `instagram` or `tiktok` |
| `story_rights` | boolean | Whether the business connection lets LanaChat post stories |
| `last_activity_at` | string | Last message sent or received, ISO 8601 UTC |

- `health` is `connected`, `pending` (the business connection is not confirmed yet) or `expired` (the bot lost access; reconnect it).
- The bot token is never returned. LanaChat never asks for a phone number, a password or a 2FA code.

## Accounts

### List accounts

`GET /accounts` · `can_setup`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `creator_id` | string | No | Only the accounts of this creator |
| `health` | string | No | `connected`, `pending` or `expired`; several separated by commas |
| `limit`, `cursor` | number, string | No | [Pagination](https://lanachat.ai/guides/api-overview/) |

```bash
curl "https://api.lanachat.ai/v1/accounts?creator_id=cr_lea&health=connected,expired" \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
```

```json
{
  "data": [
    { "id": "acc_1001", "creator_id": "cr_lea", "username": "lea_officiel", "bot_username": "lea_helper_bot", "health": "connected", "active": true, "brain_id": "br_lea_main", "pool_id": "pool_lea_fr_instagram", "market": "fr", "traffic": "instagram", "story_rights": true, "last_activity_at": "2026-10-06T13:58:20Z" },
    { "id": "acc_1004", "creator_id": "cr_lea", "username": "lea_backup", "bot_username": "lea_helper2_bot", "health": "connected", "active": true, "brain_id": "br_lea_main", "pool_id": "pool_lea_fr_instagram", "market": "fr", "traffic": "instagram", "story_rights": false, "last_activity_at": "2026-10-06T13:51:02Z" }
  ],
  "next_cursor": null
}
```

### Add an account

`POST /accounts` · `can_setup`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `creator_id` | string | Yes | The creator the account belongs to |
| `bot_token` | string | Yes | The token of the bot she linked in her Telegram Business settings |
| `market` | string | No | Language market, for example `fr` |
| `traffic` | string | No | Traffic source, for example `instagram` |

```bash
curl -X POST https://api.lanachat.ai/v1/accounts \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"creator_id": "cr_lea", "bot_token": "<bot token>", "market": "fr", "traffic": "instagram"}'
```

```json
{
  "id": "acc_1007",
  "creator_id": "cr_lea",
  "username": "lea_officiel",
  "bot_username": "lea_helper_bot",
  "health": "pending",
  "active": true,
  "brain_id": "br_lea_main",
  "pool_id": "pool_lea_fr_instagram",
  "market": "fr",
  "traffic": "instagram",
  "story_rights": false,
  "last_activity_at": null
}
```

The answer is the account (`201`) with `health: "pending"` until the creator confirms the business connection in Telegram. The bot token is checked with Telegram before anything is saved: a token Telegram refuses answers `400`. An account already active in another workspace is refused (`409`). Each account needs a licence to reply: see [Billing](https://lanachat.ai/guides/api-billing/).

### Get an account

`GET /accounts/{id}` · `can_setup`

```bash
curl https://api.lanachat.ai/v1/accounts/acc_1001 \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
```

The answer is the account object, with its load this hour. An unknown id answers `404`.

### Update an account

`PATCH /accounts/{id}` · `can_setup`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `brain_id` | string | No | The brain that answers on this account |
| `market` | string | No | Language market; moves the account to the matching pool |
| `traffic` | string | No | Traffic source; moves the account to the matching pool |
| `active` | boolean | No | `false` turns the account off, `true` turns it back on |

The alias and the reply language of the account can be changed the same way.

```bash
curl -X PATCH https://api.lanachat.ai/v1/accounts/acc_1004 \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"traffic": "tiktok", "active": true}'
```

The answer is the updated account. Turning off the last sending account of a creator who has active links answers `409`.

### Disconnect an account

`DELETE /accounts/{id}` · `can_setup`

```bash
curl -X DELETE https://api.lanachat.ai/v1/accounts/acc_1004 \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
```

Its conversations are kept. Removing the last sending account of a creator who has active links answers `409`.

### Check the connection now

`POST /accounts/{id}/check` · `can_setup`

```bash
curl -X POST https://api.lanachat.ai/v1/accounts/acc_1001/check \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
```

LanaChat checks every account once an hour; this call tests it now. The answer is the account with its fresh `health`.

## Pools

A pool is formed by its accounts' tags (`market` and `traffic`); there is nothing to create. A new conversation goes to the pool whose traffic matches the link source and whose market matches the fan's language, then to the creator's "All traffic" pool, then to any of her pools that still sends. Existing conversations always stay on their account.

### List pools

`GET /pools` · `can_tracking`

```bash
curl https://api.lanachat.ai/v1/pools \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
```

```json
{
  "data": [
    {
      "id": "pool_lea_fr_instagram",
      "name": "French · Instagram",
      "creator_id": "cr_lea",
      "accounts": ["acc_1001", "acc_1004"],
      "sent_last_hour": 312,
      "capacity_per_hour": 400,
      "status": "near"
    }
  ],
  "next_cursor": null
}
```

`status` is `sending`, `near` (80% of its capacity), `saturated` (95%) or `none` (no sending account).

### Get the pool settings

`GET /pools/settings` · `can_tracking`

```bash
curl https://api.lanachat.ai/v1/pools/settings \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
```

```json
{
  "cap_per_hour": 2000,
  "default_limit_per_hour": 200,
  "distribution": { "mode": "weighted", "warmup": true, "hold_when_saturated": true }
}
```

| Field | Type | Description |
|---|---|---|
| `cap_per_hour` | number | Messages the whole workspace may send in a rolling hour, 100 to 100,000 |
| `default_limit_per_hour` | number | Hourly limit given to a new account in the pool |
| `distribution.mode` | string | `weighted` (random, in proportion to each account's weight), `round_robin` (each account in turn) or `least_loaded` (the account furthest from its limit) |
| `distribution.warmup` | boolean | A new account starts at 50 messages an hour and reaches its full limit on day 7 |
| `distribution.hold_when_saturated` | boolean | When no account can take a new fan, hold the fan until one frees up, oldest first; otherwise give the fan to the least loaded account even above its limit |

When the workspace reaches `cap_per_hour`, links keep redirecting but new conversations are held until the hour drops under the cap.

### Change the pool settings

`PUT /pools/settings` · `can_tracking`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `cap_per_hour` | number | Yes | 100 to 100,000, whole number |
| `default_limit_per_hour` | number | Yes | 10 to 1,000, whole number |
| `distribution` | object | Yes | `mode`, `warmup` and `hold_when_saturated`, as above |

```bash
curl -X PUT https://api.lanachat.ai/v1/pools/settings \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"cap_per_hour": 3000, "default_limit_per_hour": 200, "distribution": {"mode": "least_loaded", "warmup": true, "hold_when_saturated": true}}'
```

The answer is the new settings. A cap outside 100 to 100,000 answers `400`.

### Change an account in the pool

`PATCH /pools/accounts/{account_id}` · `can_tracking`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `in_pool` | boolean | No | `false` takes the account out of the pool: it keeps its conversations but gets no new fan |
| `paused` | boolean | No | `true` pauses it in the pool |
| `weight` | number | No | 0 to 100; share of new fans in `weighted` mode (0 is allowed: no new fan) |
| `limit_per_hour` | number | No | 10 to 1,000 messages an hour for this account |

```bash
curl -X PATCH https://api.lanachat.ai/v1/pools/accounts/acc_1004 \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"weight": 40, "limit_per_hour": 300}'
```

```json
{
  "account_id": "acc_1004",
  "creator_id": "cr_lea",
  "username": "lea_backup",
  "in_pool": true,
  "paused": false,
  "weight": 40,
  "limit_per_hour": 300,
  "sent_last_hour": 88,
  "new_conversations_today": 41,
  "state": "active",
  "flood_wait_until": null,
  "warmup_day": 7,
  "added_at": "2026-09-20T10:00:00Z"
}
```

- `state` is `active` or `flood_wait`: on a Telegram flood wait the account pauses itself until `flood_wait_until`, then resumes on its own.
- During warm-up (`warmup_day` 1 to 7) the account sends less than its `limit_per_hour`: 50 an hour on day 1, the full limit on day 7.
- Taking out, pausing or removing the last sending account of a creator who has active links is refused (`409`).

### Read the pool log

`GET /pools/events` · `can_tracking`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `creator_id` | string | No | Only the events of this creator's accounts |
| `limit`, `cursor` | number, string | No | [Pagination](https://lanachat.ai/guides/api-overview/) |

```bash
curl "https://api.lanachat.ai/v1/pools/events?creator_id=cr_lea&limit=2" \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
```

```json
{
  "data": [
    { "at": "2026-10-06T13:40:12Z", "kind": "resumed", "creator_id": "cr_lea", "account_id": "acc_1004", "text": "@lea_backup is sending again." },
    { "at": "2026-10-06T13:25:12Z", "kind": "flood_wait", "creator_id": "cr_lea", "account_id": "acc_1004", "text": "@lea_backup hit a Telegram flood wait of 900 seconds." }
  ],
  "next_cursor": "eyJhdCI6IjIwMjYtMTAtMDZUMTM6MjU6MTJaIn0"
}
```

`kind` is `flood_wait`, `account_paused`, `resumed`, `link_paused` (the workspace cap was reached, new fans are held), `account_added`, `account_removed` or `settings`. `text` is a plain English sentence.

## Stories

### List stories

`GET /stories` · `can_setup`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `creator_id` | string | No | Only this creator's stories |
| `status` | string | No | For example `scheduled` |
| `limit`, `cursor` | number, string | No | [Pagination](https://lanachat.ai/guides/api-overview/) |

```bash
curl "https://api.lanachat.ai/v1/stories?creator_id=cr_lea&status=scheduled" \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
```

```json
{
  "data": [ { "id": "sto_88", "status": "scheduled", "run_at": "2026-10-06T19:00:00Z", "account_ids": ["acc_1001", "acc_1004"] } ],
  "next_cursor": null
}
```

### Post a story

`POST /stories` · `can_setup`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `account_ids` | array of strings | Yes | The accounts that post it |
| `media_id` | string | Yes | A photo or video of the creator's [Vault](https://lanachat.ai/guides/api-vault/) |
| `text` | string | No | Caption |
| `link_id` | string | No | A [tracking link](https://lanachat.ai/guides/api-tracking/) shown on the story |
| `duration_hours` | number | No | How long the story stays up |
| `run_at` | string or null | No | When to post it (ISO 8601 UTC); leave it out to post now |

```bash
curl -X POST https://api.lanachat.ai/v1/stories \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"account_ids": ["acc_1001", "acc_1004"], "media_id": "med_5521", "text": "New set tonight", "link_id": "lnk_3", "duration_hours": 24, "run_at": "2026-10-06T19:00:00Z"}'
```

```json
{ "id": "sto_88", "status": "scheduled", "run_at": "2026-10-06T19:00:00Z", "account_ids": ["acc_1001", "acc_1004"] }
```

An account without the "manage stories" right in its business connection (`story_rights: false`) is refused, with the reason in `message`.

### Get a story

`GET /stories/{id}` · `can_setup`

```bash
curl https://api.lanachat.ai/v1/stories/sto_88 \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
```

The answer is the story with its views, reactions and link clicks once it is posted.

### Cancel a scheduled story

`DELETE /stories/{id}` · `can_setup`

```bash
curl -X DELETE https://api.lanachat.ai/v1/stories/sto_88 \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
```

Only a scheduled story can be cancelled.

## Related

- [LanaChat API: quick start, authentication and errors](https://lanachat.ai/guides/api-overview/)
- [Telegram Accounts: accounts, pool load and stories](https://lanachat.ai/guides/telegram-accounts/)
- [Connect Telegram accounts (and what a business connection is)](https://lanachat.ai/guides/connect-telegram/)
