Reseller API

Connect your own panel or app to SMM Panel. The API follows the standard SMM panel API v2, so most panel scripts can add us as a provider with the endpoint below and your key.

https://abisektamang.com/api/v2

Quick start

  1. Create an API key on the API access page. Choose what the key may do and, if you like, which IP addresses may use it. The key is shown only once, so store it somewhere safe.
  2. Send a POST request to the endpoint with your key and an action.
  3. Read the JSON response. Problems come back as {"error": "…"}, so check for an error field in every response.
Example request
curl -X POST https://abisektamang.com/api/v2 \
  -d key=YOUR_API_KEY \
  -d action=balance

Requests and responses

ItemDetails
Endpointhttps://abisektamang.com/api/v2
MethodPOST. GET with a query string also works, but it can leave your key in server logs, so prefer POST.
BodyForm fields (application/x-www-form-urlencoded or multipart/form-data), or a JSON object sent with Content-Type: application/json.
ResponseJSON in UTF-8.
AmountsStrings in NPR with 2 to 5 decimals, for example "163.03" or "0.8631".
Several IDsPut them in one parameter, separated by commas or spaces, up to 100 per request.

Keys and permissions

Every request needs your key. Each key has its own permissions. Using an action the key is not allowed to use returns an error.

PermissionActions
List servicesservices
Place ordersadd
Check order statusstatus
Check balancebalance
Request refillsrefill, refill_status
Request cancellationscancel

If you limit a key to certain IP addresses, requests from any other address get an error. Call the API from your own server and never put your key in a web page or app that other people can inspect. Lost a key? Rotate or revoke it on the API access page.

Service list

Returns every service you can order, with your prices after any account discount.

ParameterRequiredDescription
keyYesYour API key.
actionYesservices
Request
curl -X POST https://abisektamang.com/api/v2 \
  -d key=YOUR_API_KEY \
  -d action=services
Response
[
    {
        "service": 1,
        "name": "Instagram Followers",
        "type": "Default",
        "category": "Instagram",
        "rate": "163.03",
        "min": "50",
        "max": "50000",
        "refill": true,
        "cancel": true,
        "dripfeed": false
    },
    {
        "service": 4,
        "name": "Instagram Custom Comments",
        "type": "Custom Comments",
        "category": "Instagram",
        "rate": "863.10",
        "min": "5",
        "max": "1000",
        "refill": false,
        "cancel": false,
        "dripfeed": false
    }
]
FieldMeaning
serviceService ID to use with add.
typeWhich parameters add needs. See the table of service types below.
ratePrice per 1,000 in NPR, or per order for the Package type.
min, maxSmallest and largest quantity per order.
refill, cancel, dripfeedWhether refills, cancellations and drip-feed are available.

Add an order

Places an order and pays for it from your balance right away. The response is the new order ID.

ParameterRequiredDescription
keyYesYour API key.
actionYesadd
serviceYesService ID from the service list.
linkMost typesPublic link to the profile, post or video. Never send a password.
quantityMost typesHow many to deliver, between the service min and max.
runsNoDrip-feed: number of deliveries, 2 to 1,000.
intervalNoDrip-feed: minutes between deliveries, 1 to 10,080.
idempotency_keyNoYour own unique reference for this order. See avoiding duplicate orders below. client_key and external_id work too.
Request
curl -X POST https://abisektamang.com/api/v2 \
  -d key=YOUR_API_KEY \
  -d action=add \
  -d service=1 \
  --data-urlencode "link=https://www.instagram.com/yourprofile/" \
  -d quantity=1000
Response
{
    "order": 23501
}

Parameters by service type

The type in the service list tells you what to send besides service.

TypeParameters
Defaultlink, quantity
Packagelink. The price is per order, so no quantity.
Custom Commentslink, comments: one comment per line. The number of lines is the quantity.
Mentions Custom Listlink, usernames: one username per line. The number of lines is the quantity.
Mentions Hashtaglink, quantity, hashtag
Mentions User Followerslink, quantity, username
Comment Likeslink, quantity, username of the comment author
Polllink, quantity, answer_number from 1 to 20
Subscriptionsusername, min and max per post, posts (1 to 1,000 new posts), delay in minutes (0, 5, 10, 15, 30, 60 or 90) and optionally expiry, a future date as YYYY-MM-DD or DD/MM/YYYY. The charge covers max × posts.

In one-per-line fields, separate lines with a newline or with the two characters \n.

Drip-feed

For services with "dripfeed": true, send runs and interval to split delivery over time. The quantity is delivered in every run, so the charge is the price of quantity × runs.

Avoiding duplicate orders

Network errors happen. Send idempotency_key with a value that is unique for each of your orders. If you retry with a key you already used, for the same service, link and quantity, you get the original order ID back and are not charged again. The same key with other order details is refused with an error. Keys are compared without regard to letter case or accents, and webhooks repeat a key of up to 60 characters exactly as you sent it.

Some services refuse a second active order for the same link. In that case the response is an error naming the active order.

Order status

ParameterRequiredDescription
keyYesYour API key.
actionYesstatus
orderOne of theseA single order ID.
ordersOne of theseUp to 100 order IDs, separated by commas.
Request
curl -X POST https://abisektamang.com/api/v2 \
  -d key=YOUR_API_KEY \
  -d action=status \
  -d order=1001
Response
{
    "charge": "16.30",
    "start_count": "1250",
    "status": "In progress",
    "remains": "430",
    "currency": "NPR"
}
Response for several orders
{
    "1001": {
        "charge": "16.30",
        "start_count": "1250",
        "status": "In progress",
        "remains": "430",
        "currency": "NPR"
    },
    "1002": {
        "error": "Incorrect order ID"
    }
}
FieldMeaning
chargeWhat the order cost, minus anything refunded.
start_countThe count when delivery started, or "0" when unknown.
remainsHow many are still to be delivered.
statusPending (received, not started yet), Processing, In progress, Completed, Partial (part delivered, the rest refunded) or Canceled (refunded).
currencyCurrency of charge.

Refills

For services with "refill": true. An order can be refilled once it is completed or partial, within the refill period of its service, at most once every 24 hours and one refill at a time.

ParameterRequiredDescription
actionYesrefill to request a refill, refill_status to check one.
order / ordersFor refillOne order ID, or up to 100 separated by commas.
refill / refillsFor refill_statusOne refill ID, or up to 100 separated by commas.
Request
curl -X POST https://abisektamang.com/api/v2 \
  -d key=YOUR_API_KEY \
  -d action=refill \
  -d order=1001
Response
{
    "refill": 412
}
Response for several orders
[
    {
        "order": 1001,
        "refill": 412
    },
    {
        "order": 1002,
        "refill": {
            "error": "The refill period for this order has ended."
        }
    }
]
refill_status response
{
    "status": "Completed"
}
refill_status response for several refills
[
    {
        "refill": 412,
        "status": "Completed"
    },
    {
        "refill": 413,
        "status": {
            "error": "Refill not found"
        }
    }
]

Refill status is Pending, In progress, Completed or Rejected.

Cancel orders

For services with "cancel": true. Orders that have not started are canceled and refunded right away. Orders already being delivered get a cancellation request, and their status shows the result.

ParameterRequiredDescription
actionYescancel
ordersYesUp to 100 order IDs, separated by commas. A single order also works.
Request
curl -X POST https://abisektamang.com/api/v2 \
  -d key=YOUR_API_KEY \
  -d action=cancel \
  -d orders=1001,1002
Response
[
    {
        "order": 1001,
        "cancel": 1
    },
    {
        "order": 1002,
        "cancel": {
            "error": "This order can no longer be canceled."
        }
    }
]

Balance

Your current balance, including any promotional balance.

Request
curl -X POST https://abisektamang.com/api/v2 \
  -d key=YOUR_API_KEY \
  -d action=balance
Response
{
    "balance": "1520.75",
    "currency": "NPR"
}

Errors

Every error is a JSON object with an error message, like {"error": "Incorrect service ID"}. As in other SMM panels, every answer comes with HTTP status 200, errors included, so always check for error.

ErrorWhen
API key is requiredThe request has no key.
Invalid API keyThe key is wrong or was revoked, or API access is turned off for the account.
This API key is not allowed to use this actionThe key does not have permission for this action.
The API is disabled.The API is turned off for this panel.
Too many requestsToo many requests from your IP address, or too many invalid keys. Wait for the number of seconds in the Retry-After header.
Rate limit exceeded for this keyThis key sent more requests in a minute than it may. Wait for the number of seconds in the Retry-After header.
Maintenance in progress, please retry laterMaintenance in progress. Try again later.

Messages you may see:

  • API key is required
  • Invalid API key
  • Incorrect action
  • Incorrect service ID
  • Incorrect order ID
  • Refill not found
  • Not enough funds in your balance.
  • Quantity must be between 50 and 50,000.
  • This API key is not allowed to use this action
  • Rate limit exceeded for this key

Rate limits

  • Each key can make up to 120 requests per minute.
  • Each IP address can make up to 600 requests per minute across all keys.
  • After more than 30 requests with an invalid key from one IP address within 10 minutes, further invalid attempts get Too many requests.

Over a limit, you get the error Too many requests or Rate limit exceeded for this key with the header Retry-After: 60. To stay well within limits, check up to 100 orders per request with orders instead of one request per order.

Webhooks

Instead of polling status, let us call you. On the API access page, enter one https:// address and you get a signing secret. From then on every status change of your orders and refills is sent to that address as a JSON POST request. Delivery is asynchronous (within about a minute) and retried for up to a day.

Events

EventSent when
order.processingThe order was accepted by the provider.
order.in_progressDelivery has started.
order.completedThe order is complete.
order.partialPart of the order was delivered; the rest was refunded. order.refunded holds the amount.
order.canceledThe order was canceled and refunded (by you, by staff or by the provider). order.refunded holds the amount.
refill.in_progressA refill was accepted by the provider.
refill.completedThe refill is complete.
refill.rejectedThe refill was refused. refill.reason says why, when known.
test.pingSent by the "Send test event" button.

Request

HeaderMeaning
Content-Typeapplication/json
X-Panel-EventThe event name, for example order.completed.
X-Panel-TimestampUnix time (seconds) when the delivery was sent. Refuse deliveries older than a few minutes.
X-Panel-Signaturesha256= followed by the hex HMAC-SHA256 of <timestamp>.<raw body>, keyed with your signing secret.
X-Panel-DeliveryA number that identifies this delivery. Retries send the same number, so you can ignore duplicates.
Body of an order event
{
    "id": 8812,
    "event": "order.completed",
    "created_at": "2026-10-22T09:14:05+00:00",
    "status": "Completed",
    "previous_status": "In progress",
    "order": {
        "id": 23501,
        "status": "Completed",
        "service": 1,
        "service_name": "Instagram Followers",
        "link": "https://www.instagram.com/yourprofile/",
        "quantity": 1000,
        "start_count": 1250,
        "remains": 0,
        "charge": "163.03",
        "refunded": "0.00",
        "currency": "NPR",
        "idempotency_key": "my-order-1001",
        "created_at": "2026-10-22T08:40:11+00:00",
        "updated_at": "2026-10-22T09:14:05+00:00"
    }
}
Body of a refill event
{
    "id": 8813,
    "event": "refill.completed",
    "created_at": "2026-10-23T11:02:40+00:00",
    "status": "Completed",
    "refill": {
        "id": 412,
        "order": 23501,
        "status": "Completed",
        "reason": null,
        "created_at": "2026-10-23T09:00:00+00:00",
        "updated_at": "2026-10-23T11:02:40+00:00"
    }
}
FieldMeaning
status, previous_statusThe status that triggered the event and the one before it, with the same names as the status action.
orderThe order as it is when the event is sent: charge is what it cost after refunds, refunded what went back to your balance, remains what is still to deliver, idempotency_key your own reference if you sent one.
refillThe refill with its order ID, status (Pending, In progress, Completed or Rejected) and reason.
created_atWhen the event happened, ISO 8601 in UTC.

Verifying and answering

  1. Read the raw request body (not a re-encoded version of it) and compute sha256= + HMAC-SHA256(secret, timestamp + "." + body), where timestamp is the X-Panel-Timestamp header. Compare it with X-Panel-Signature using a constant-time comparison and refuse deliveries whose timestamp is more than five minutes old.
  2. Answer with any HTTP 2xx status within 10 seconds. Queue slow work instead of doing it before you answer.
  3. Anything else (timeouts, 3xx, 4xx, 5xx) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours. After 20 failures in a row the webhook is turned off and you are notified; turn it on again from the API access page once your endpoint works.
  4. Events can arrive out of order when retries are involved: use order.status (the current state) rather than the event name when in doubt, and keep the latest updated_at.

Only https:// addresses on public hosts are accepted. We do not follow redirects, so point the address straight at your script.

PHP
<?php
// webhook.php: verify the signature, then handle the event. Answer 200 quickly; do the slow work later.
$secret = 'YOUR_SIGNING_SECRET';
$body = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_PANEL_SIGNATURE'] ?? '';
$timestamp = (int) ($_SERVER['HTTP_X_PANEL_TIMESTAMP'] ?? 0);
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret);
if (!hash_equals($expected, $signature) || abs(time() - $timestamp) > 300) {
    http_response_code(401);
    exit('bad signature or stale delivery');
}
$event = json_decode($body, true);
$deliveryId = (int) ($_SERVER['HTTP_X_PANEL_DELIVERY'] ?? 0); // the same ID is sent again on retries: ignore duplicates
switch ($event['event'] ?? '') {
    case 'order.completed':
    case 'order.partial':
    case 'order.canceled':
        // $event['order']['id'], $event['order']['status'], $event['order']['refunded'] ...
        break;
    case 'refill.completed':
    case 'refill.rejected':
        // $event['refill']['id'], $event['refill']['order'], $event['refill']['status']
        break;
}
http_response_code(200);
Python
# Flask example: verify the signature, then handle the event.
import hashlib, hmac, json, time
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = b"YOUR_SIGNING_SECRET"

@app.post("/webhook")
def webhook():
    body = request.get_data()  # raw bytes, exactly as sent
    timestamp = request.headers.get("X-Panel-Timestamp", "0")
    expected = "sha256=" + hmac.new(SECRET, timestamp.encode() + b"." + body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, request.headers.get("X-Panel-Signature", "")) or abs(time.time() - int(timestamp)) > 300:
        abort(401)
    event = json.loads(body)
    delivery_id = request.headers.get("X-Panel-Delivery")  # same ID on retries: ignore duplicates
    if event["event"].startswith("order."):
        order = event["order"]  # order["id"], order["status"], order["remains"], order["refunded"]
    elif event["event"].startswith("refill."):
        refill = event["refill"]  # refill["id"], refill["order"], refill["status"]
    return "", 200

Code examples

curl, form fields
curl -X POST https://abisektamang.com/api/v2 \
  -d key=YOUR_API_KEY \
  -d action=add \
  -d service=1 \
  --data-urlencode "link=https://www.instagram.com/yourprofile/" \
  -d quantity=1000 \
  -d idempotency_key=my-order-1001
curl, JSON body
curl -X POST https://abisektamang.com/api/v2 \
  -H "Content-Type: application/json" \
  -d '{"key":"YOUR_API_KEY","action":"status","orders":"1001,1002"}'
PHP
<?php
// Calls the API and returns the decoded JSON, or throws on an error.
function smm_api(array $params): array
{
    $ch = curl_init('https://abisektamang.com/api/v2');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query(['key' => 'YOUR_API_KEY'] + $params),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30,
    ]);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $data = json_decode((string) $body, true);
    if (!is_array($data)) {
        throw new RuntimeException('Unexpected response (HTTP ' . $status . ')');
    }
    if (isset($data['error'])) {
        throw new RuntimeException($data['error']);
    }
    return $data;
}

// Place an order. Retrying with the same idempotency_key returns the same order.
$order = smm_api([
    'action' => 'add',
    'service' => 1,
    'link' => 'https://www.instagram.com/yourprofile/',
    'quantity' => 1000,
    'idempotency_key' => 'my-order-1001',
]);
echo 'Order ID: ' . $order['order'] . PHP_EOL;

// Check its progress later.
$status = smm_api(['action' => 'status', 'order' => $order['order']]);
echo $status['status'] . ', remaining: ' . $status['remains'] . PHP_EOL;