# LarkPanel API v2

Standard SMM panel API (compatible with the common "API v2" used by most SMM panels).

- Endpoint: `https://api.larkpanel.com/api/v2`
- Method: `POST` (recommended). Body as `application/x-www-form-urlencoded`, `multipart/form-data` or `application/json`. `GET` with query string parameters is also accepted.
- Authentication: parameter `key` = your API key (create it on the "API" page of your account; it is shown only once). Each key belongs to one account (org) and one currency.
- Response: JSON, HTTP 200. Errors are returned as `{"error": "<message>", "error_code": "<CODE>", "details": "<optional text>"}` with HTTP 200, except rate limit (HTTP 429) and payload too large (HTTP 413) which use the same JSON shape.
- Rate limit: 120 requests per minute per API key (plus a per-IP limit at the gateway).
- Machine-readable: this document at `https://api.larkpanel.com/api/v2/docs.md`, OpenAPI at `https://api.larkpanel.com/api/v2/openapi.json`, summary at `https://api.larkpanel.com/llms.txt`.

## Parameters common to every action

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | string | yes | API key, e.g. `lp_xxxxxxxx...` |
| `action` | string | yes | One of `services`, `add`, `status`, `cancel`, `balance` |

## Money and currency

- All amounts (`rate`, `charge`, `balance`) are strings in the currency of the API key (`USD` by default, chosen when the key is created). Up to 6 decimals.
- `rate` is the price per 1000 units using your own account price (account and level discounts included). For services of type `Custom Comments` one unit is one comment line. For a service without quantity the price of one order is `rate / 1000` and `quantity` is ignored.
- Orders are charged from your balance after they are accepted. `add` refuses the order when balance plus credit limit is lower than the estimated price.
- No automatic refund: canceled or partial orders are reviewed by the site and refunded manually when applicable. A TikTok video views order the provider could not start is reported as `Canceled` (natural views of the video are not counted as delivered).

## services

List services you can order.

Parameters: `key`, `action=services`.

Example request:

```bash
curl -X POST https://api.larkpanel.com/api/v2 -d key=YOUR_API_KEY -d action=services
```

Example response:

```json
[
  {
    "service": 100,
    "name": "Facebook live views · 60 phút",
    "type": "Default",
    "category": "Facebook - Livestream",
    "rate": "0.90",
    "min": "10",
    "max": "10000",
    "refill": false,
    "cancel": true
  },
  {
    "service": 200,
    "name": "Facebook custom comments",
    "type": "Custom Comments",
    "category": "Facebook - Comments",
    "rate": "12.50",
    "min": "1",
    "max": "1000",
    "refill": false,
    "cancel": true
  }
]
```

Fields: `service` (integer ID to use in `add`), `name`, `type` (`Default` or `Custom Comments`), `category` ("<platform> - <category>"), `rate` (price per 1000, string), `min` / `max` (quantity bounds, strings; number of lines for Custom Comments), `refill` (always false), `cancel` (always true).
Services that offer options (duration, reaction type...) are listed once per option combination, each with its own `service` ID. Each service owns a block of 100 IDs: the hundreds identify the service (100, 200, 300...) and the last two digits the option combination (100, 101, 102...). IDs never change and are never reused. Services under maintenance stay listed and can be ordered: the order waits in the queue and starts when the service is available again, with no guaranteed completion time. Locked services are not listed (ordering one answers `SERVICE_LOCKED`).

## add

Create an order.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `service` | integer | yes | Service ID from `services` |
| `link` | string (URL) | yes | Target link (must match the platform of the service, e.g. facebook.com) |
| `quantity` | integer | yes for type `Default` | Between `min` and `max` of the service |
| `comments` | string | yes for type `Custom Comments` | One comment per line (newline separated). Quantity = number of non-empty lines; `quantity` is ignored |

Example request:

```bash
curl -X POST https://api.larkpanel.com/api/v2 -d key=YOUR_API_KEY -d action=add -d service=1 -d link=https://www.facebook.com/page/videos/123 -d quantity=100
```

Example response:

```json
{ "order": 23501 }
```

Possible errors: `INCORRECT_SERVICE`, `SERVICE_LOCKED`, `SERVICE_PRICE_MISSING`, `INCORRECT_LINK`, `INCORRECT_QUANTITY`, `INCORRECT_COMMENTS`, `INCORRECT_REQUEST`, `NOT_ENOUGH_FUNDS`.

## status

Get the status of one order (`order`) or up to 100 orders (`orders`). Every order of the account has a numeric ID, including orders placed on the website (shown as "API ID" in the order details), so they can be tracked and canceled here too. Orders of other accounts are never visible.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `order` | integer | one of `order` / `orders` | Order ID returned by `add` (or the API ID of a website order) |
| `orders` | string | one of `order` / `orders` | Comma-separated order IDs, max 100, e.g. `1,2,3` |

Example request (single):

```bash
curl -X POST https://api.larkpanel.com/api/v2 -d key=YOUR_API_KEY -d action=status -d order=23501
```

Example response (single):

```json
{ "charge": "0.27819", "start_count": "3572", "status": "Partial", "remains": "157", "currency": "USD" }
```

Example request (multiple):

```bash
curl -X POST https://api.larkpanel.com/api/v2 -d key=YOUR_API_KEY -d action=status -d orders=1,10,100
```

Example response (multiple):

```json
{
  "1": { "charge": "0.27819", "start_count": "3572", "status": "Partial", "remains": "157", "currency": "USD" },
  "10": { "error": "Incorrect order ID", "error_code": "INCORRECT_ORDER" },
  "100": { "charge": "1.44219", "start_count": "234", "status": "In progress", "remains": "10", "currency": "USD" }
}
```

Fields: `charge` (amount originally charged for the order; refunds are not subtracted, string), `start_count` (string), `status` (see "Order status values"), `remains` (units not delivered yet, string), `currency`.

## cancel

Cancel one or more orders (max 100). Orders already running are canceled at the provider when it supports it. No automatic refund.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `orders` | string | one of `orders` / `order` | Comma-separated order IDs, max 100 |
| `order` | integer | one of `orders` / `order` | A single order ID |

Example request:

```bash
curl -X POST https://api.larkpanel.com/api/v2 -d key=YOUR_API_KEY -d action=cancel -d orders=2,9
```

Example response:

```json
[
  { "order": 2, "cancel": 1 },
  { "order": 9, "cancel": { "error": "Incorrect order ID", "error_code": "INCORRECT_ORDER" } }
]
```

Per-order errors: `INCORRECT_ORDER`, `CANCEL_NOT_ALLOWED` (status does not allow cancel, see `details`), `CANCEL_IN_PROGRESS` (order is being processed right now, retry later).

## balance

Get the balance of the account in the key currency.

Parameters: `key`, `action=balance`.

Example request:

```bash
curl -X POST https://api.larkpanel.com/api/v2 -d key=YOUR_API_KEY -d action=balance
```

Example response:

```json
{ "balance": "100.84292", "currency": "USD" }
```

## refill

Not supported. Always returns `{"error": "Refill is not supported", "error_code": "REFILL_NOT_SUPPORTED"}`.

## Order status values

| Status | Meaning |
| --- | --- |
| `Pending` | Order received and being checked, charged or queued (internal: pending, enriching, awaiting_payment, charging, queued, delivering). |
| `In progress` | Order is running at the provider, paused, refilling or delayed (internal: running, renewal_due, paused, refilling, delayed). |
| `Completed` | Order finished (internal: done). |
| `Partial` | Order was canceled or stopped after part of it was delivered (internal: canceled/stopped with delivered count > 0). Refund, if any, is reviewed manually by the site. |
| `Canceled` | Order was canceled or stopped before anything was delivered, or failed (internal: canceled/stopped with nothing delivered, failed). |

## Errors

Every error has the shape `{"error": "<message>", "error_code": "<CODE>", "details": "<optional>"}`. Messages and codes are stable; act on `error_code`.

| error_code | error |
| --- | --- |
| `INVALID_KEY` | Invalid API key |
| `ACCOUNT_DISABLED` | Account is disabled |
| `CURRENCY_UNAVAILABLE` | Currency of this API key is no longer available |
| `RATE_LIMITED` | Too many requests |
| `INCORRECT_ACTION` | Incorrect action |
| `REFILL_NOT_SUPPORTED` | Refill is not supported |
| `INCORRECT_SERVICE` | Incorrect service ID |
| `SERVICE_MAINTENANCE` | Service is under maintenance |
| `SERVICE_LOCKED` | Service is locked |
| `SERVICE_PRICE_MISSING` | Service price is not configured |
| `INCORRECT_LINK` | Incorrect link |
| `INCORRECT_QUANTITY` | Incorrect quantity |
| `INCORRECT_COMMENTS` | Incorrect comments |
| `INCORRECT_REQUEST` | Incorrect request |
| `NOT_ENOUGH_FUNDS` | Not enough funds on balance |
| `INCORRECT_ORDER` | Incorrect order ID |
| `TOO_MANY_ORDERS` | Too many order IDs (max 100) |
| `CANCEL_NOT_ALLOWED` | Order cannot be canceled |
| `CANCEL_IN_PROGRESS` | Order is being processed, try again later |
| `PAYLOAD_TOO_LARGE` | Payload too large |
| `INTERNAL` | Internal error |

## Example flow

1. `action=balance` to check funds.
2. `action=services`, pick a `service` ID and read `min`, `max`, `type`, `rate`.
3. `action=add` with `service`, `link` and `quantity` (or `comments`), keep the returned `order`.
4. Poll `action=status` with `orders=<id1>,<id2>` every few minutes until status is `Completed`, `Partial` or `Canceled`.
5. Optionally `action=cancel` with `orders=<id>`.

## PHP example

```php
<?php
function larkpanel_api(array $params) {
    $params['key'] = 'YOUR_API_KEY';
    $ch = curl_init('https://api.larkpanel.com/api/v2');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    curl_close($ch);
    return json_decode($result, true);
}

$services = larkpanel_api(['action' => 'services']);
$order = larkpanel_api(['action' => 'add', 'service' => 1, 'link' => 'https://www.facebook.com/page/videos/123', 'quantity' => 100]);
$status = larkpanel_api(['action' => 'status', 'order' => $order['order']]);
$balance = larkpanel_api(['action' => 'balance']);
```
