API · v2

One endpoint, seven actions. PerfectPanel-compatible.

Existing integrations point here by swapping the base URL and the key — same POST, same form-encoded body, same JSON shapes. Seven actions cover services, orders, refills, cancels, and wallet balance.

  • PerfectPanel-compatible
  • Scoped, revocable keys
  • Published rate limits
POST /api/v2 · action=add
curl -X POST "https://smmhub.io/api/v2" \
  -d "key=YOUR_API_KEY" \
  -d "action=add" \
  -d "service=1042" \
  -d "link=https://instagram.com/your_handle" \
  -d "quantity=1000"

# response
{ "order": 100482 }
POSThttps://smmhub.io/api/v2

All requests are POST with application/x-www-form-urlencoded payloads. Responses are JSON.

Getting started

Up and running in three steps

The whole API is one URL and a flat list of action values. A key, a smoke test, and the conventions below cover everything.

1. Get an API key

Sign up, then head to Account → API in the dashboard. Keys are shown once at creation and stored hashed, and each one can be revoked individually. Pick the orders scope if your integration places orders.

2. Smoke test with cURL

Paste this in your terminal — replace YOUR_API_KEY with the one you just generated. If you see your wallet balance, the key works.

curl -X POST "https://smmhub.io/api/v2" \
  -d "key=YOUR_API_KEY" \
  -d "action=balance"

# response
{ "balance": "247.304", "currency": "USD" }

3. Conventions

  • HTTP

    One verb: POST. One URL: /api/v2.

  • Body

    Form-encoded (application/x-www-form-urlencoded). No JSON bodies.

  • Auth

    The key travels as a body field — no auth headers.

  • Responses

    Always JSON. Errors are HTTP 200 with an error field — only 401, 403, and 429 use real statuses.

  • Batching

    status, cancel, refill, and refill_status accept comma-separated IDs — up to 100 per call.

  • Idempotency

    Optional Idempotency-Key header on add — retries are safe, replays never place a second order.

Services

List the live catalog with rates, limits, and capability flags.

POST/api/v2action=services

Service list

Returns the full live catalog: rate per 1,000, min/max, and per-service capability flags (refill, cancel, dripfeed). Cache it on your side — a minute is plenty.

Parameters

  • keystringrequiredfixed

    Your private API key from Account → API.

  • actionstringrequiredfixed

    Must be the literal string services.

Notes

  • Rates are per 1,000 units in USD. min and max are strings on the wire — the canonical PerfectPanel shape.
  • The type field tells you which add variant applies: Default, Package, Custom Comments, Mentions, Subscriptions, or Drip-feed.
  • Per-kind extras (fixed_quantity, posts_per_delivery, max_runs_count) appear only on rows they apply to.
curl -X POST "https://smmhub.io/api/v2" \
-d "key=YOUR_API_KEY" \
-d "action=services"
[
{
"service": 1042,
"name": "Instagram Followers — High Quality",
"type": "Default",
"category": "Instagram | Followers",
"rate": "0.85",
"min": "50",
"max": "100000",
"refill": true,
"cancel": true,
"dripfeed": true
},
{
"service": 2207,
"name": "TikTok Views — Package",
"type": "Package",
"category": "Tiktok | Views",
"rate": "1.20",
"min": "1000",
"max": "1000",
"refill": false,
"cancel": false,
"dripfeed": false,
"fixed_quantity": 1000
}
]
Orders

Place orders, look up status, and cancel in flight.

POST/api/v2action=add

Add order

Place a new order. The catalog `type` decides which fields apply — pick the matching tab. The wallet is charged on placement; canceled or partial orders refund automatically.

Parameters

  • keystringrequiredfixed

    Your private API key from Account → API.

  • actionstringrequiredfixed

    Must be the literal string add.

  • servicenumberrequired

    Service ID from the catalog.

  • linkstringrequired

    Public link the order will be delivered to.

  • quantitynumberrequired

    How many units to deliver. Must respect the service min/max.

Notes

  • Store the returned order ID — it's the handle for status, refill, and cancel.
  • Optional: send an Idempotency-Key header. Replaying the same key never places a second order — the retry answers This order was already placed for this request.
  • Mentions services take a usernames list and Subscriptions services take posts — same one-per-line format as comments.
  • hashtags, username, min, max, and delay are not supported; sending them returns an explicit error instead of being silently dropped.
curl -X POST "https://smmhub.io/api/v2" \
-d "key=YOUR_API_KEY" \
-d "action=add" \
-d "service=1042" \
-d "link=https://instagram.com/your_handle" \
-d "quantity=1000"
{
"order": 100482
}
POST/api/v2action=status

Order status

Look up one order or a batch — the same action covers both. Pass `order` for a single lookup, or `orders` (comma-separated, up to 100) when polling.

Parameters

  • keystringrequiredfixed

    Your private API key from Account → API.

  • actionstringrequiredfixed

    Must be the literal string status.

  • ordernumberrequired

    Order ID returned by add.

Notes

  • Status values: Pending, Processing, In progress, Completed, Partial, Canceled.
  • On Partial, remains is what didn't deliver — that portion is refunded to your wallet automatically.
  • The batch shape returns { "100482": { … }, "100483": { "error": "Order not found." } } — per-ID errors never fail the whole call.
curl -X POST "https://smmhub.io/api/v2" \
-d "key=YOUR_API_KEY" \
-d "action=status" \
-d "order=100482"
{
"charge": "0.85",
"start_count": "12450",
"status": "In progress",
"remains": "240",
"currency": "USD"
}
POST/api/v2action=cancel

Cancel orders

Request cancellation for up to 100 orders in one call. Anything undelivered refunds to your wallet; work already in flight is honoured.

Parameters

  • keystringrequiredfixed

    Your private API key from Account → API.

  • actionstringrequiredfixed

    Must be the literal string cancel.

  • orderslistrequired

    Up to 100 order IDs separated by commas. This field is always required — there is no single-ID form.

Notes

  • "cancel": 1 signals acceptance. Per-row errors are wrapped inside the cancel key, matching the PerfectPanel spec.
  • Services with cancel: false in the catalog answer Cancel is not available for this service.
curl -X POST "https://smmhub.io/api/v2" \
-d "key=YOUR_API_KEY" \
-d "action=cancel" \
-d "orders=100482,100483"
[
{ "order": 100482, "cancel": 1 },
{
"order": 100483,
"cancel": { "error": "Order cannot be canceled in its current state." }
}
]
Refills

Request and track refills on eligible orders.

POST/api/v2action=refill

Create refill

Request a refill on an eligible order — single via `order`, batch via `orders` (up to 100). Eligibility and the refill window are per-service, shown in the catalog.

Parameters

  • keystringrequiredfixed

    Your private API key from Account → API.

  • actionstringrequiredfixed

    Must be the literal string refill.

  • ordernumberrequired

    Order ID to refill.

Notes

  • Refill IDs are ULID strings, not integers — store them as strings.
  • Batch shape: [ { "order": 100482, "refill": "01J2…" }, { "order": 100483, "refill": { "error": "…" } } ].
  • One refill at a time per order — a second request while one is open answers A refill is already in progress for this order.
curl -X POST "https://smmhub.io/api/v2" \
-d "key=YOUR_API_KEY" \
-d "action=refill" \
-d "order=100482"
{
"refill": "01J2ZK3AC9V7Q8XN5T4RD6WYBE"
}
POST/api/v2action=refill_status

Refill status

Track submitted refills — single via `refill`, batch via `refills` (up to 100).

Parameters

  • keystringrequiredfixed

    Your private API key from Account → API.

  • actionstringrequiredfixed

    Must be the literal string refill_status.

  • refillstringrequired

    Refill ID returned by refill.

Notes

  • Refill status values: Pending, In progress, Partial, Completed, Canceled, Error.
  • Batch shape: [ { "refill": "01J2…", "status": "Completed" }, { "refill": "01J2…", "status": { "error": "Refill not found." } } ].
curl -X POST "https://smmhub.io/api/v2" \
-d "key=YOUR_API_KEY" \
-d "action=refill_status" \
-d "refill=01J2ZK3AC9V7Q8XN5T4RD6WYBE"
{
"status": "Completed"
}
Account

Read your wallet balance and currency.

POST/api/v2action=balance

Wallet balance

Read your current wallet balance. Balances are held in USD.

Parameters

  • keystringrequiredfixed

    Your private API key from Account → API.

  • actionstringrequiredfixed

    Must be the literal string balance.

Notes

  • balance is a string with 3-decimal precision, so sub-cent amounts survive the wire.
curl -X POST "https://smmhub.io/api/v2" \
-d "key=YOUR_API_KEY" \
-d "action=balance"
{
"balance": "247.304",
"currency": "USD"
}
Reference

Keys & scopes

  • read

    services · balance · status · refill_status — safe for dashboards and monitors.

  • orders

    Everything read can do, plus add · refill · cancel — the scope for integrations.

Mutating actions (add · refill · cancel) called with a read key answer HTTP 403. Scope is fixed at creation — mint a new key to change it.

Reference

Rate limits

  • Readsservices · balance · status · refill_status600 / min
  • Order placementadd120 / min
  • Mutationsrefill · cancel60 / min

Limits are per key with a sliding window. A 429 carries Retry-After and X-RateLimit-Limit headers — back off and retry. Batch status checks (up to 100 IDs) and poll every 30–60 seconds instead of tight loops.

Reference

Errors

Error strings

Business errors come back as HTTP 200 with an error field. The strings are stable — match on a substring, not the HTTP status.

  • "Missing service. / Missing link."

    A required field was absent on add.

  • "Service not found."

    The catalog ID does not exist. Refresh your cached catalog.

  • "Service is paused."

    The service exists but is not accepting orders right now.

  • "Quantity is out of range for this service."

    The requested amount is outside the service min/max.

  • "Insufficient funds."

    The wallet cannot cover the charge. Top up and retry.

  • "This order was already placed for this request."

    An Idempotency-Key you already used was replayed — the original order stands.

  • "Order not found."

    The order ID does not exist on your account.

  • "Order cannot be canceled in its current state."

    Cancellation was requested after the order finished (or while it cannot stop).

  • "Refill is not available for this order."

    The service carries no refill term, or the order is not eligible.

  • "Refill window has closed."

    The per-service refill window has expired.

  • "A refill is already in progress for this order."

    Wait for the open refill to finish before requesting another.

  • "Refill not found."

    The refill ID does not exist on your account.

  • "Server error."

    Something failed on our side. Safe to retry with backoff.

Transport statuses

The only cases where the HTTP status itself signals the problem:

  • 401

    Missing or invalid API key.

  • 403

    Key scope is insufficient — add / refill / cancel need the orders scope.

  • 429

    Rate limit exceeded. The response carries Retry-After and X-RateLimit-Limit headers — back off and retry.

Everything else — including business failures like Insufficient funds. — is HTTP 200 with the error envelope.

Ready to integrate?

A free account gets you a key and the full catalog.