talon
AR
تحدث مع شخصتحدّث اطلب الآن
هذه الصفحة متاحة باللغة الإنجليزية فقط. اقرأها بالإنجليزية

Integration

Building against an SMM API: the four calls that matter

A panel needs four actions: services to read the catalogue, balance to know what you can spend, add to place an order, and status to follow it. The endpoint is form-encoded and answers JSON. Errors arrive in the JSON body, often with HTTP 200, so a client that checks only the status code treats a rejection as a success.

A panel integration looks larger than it is. Four actions carry the whole order path: read the catalogue, read the balance, place an order, follow it. Every other feature, from a reseller storefront to a status dashboard, is a view over those four calls and the data you store around them.

This guide walks through the four calls in the order a client uses them, the shape of each response, and the error that arrives with an HTTP 200. It uses this panel's public API as the concrete example, and it names the supplier-side constants that shape how the panel itself calls its suppliers.

The shape of the endpoint

The endpoint is a POST to /api/v2. The body is form-encoded, and every request carries two fields: the key and the action. The response is JSON. There is no XML, no GraphQL and no signed header. The key is the credential, so it belongs in a secret store, not in a repository or a screenshot.

The public API has 4 actions: services, balance, add and status. That is the whole surface. Refill, cancel, sub-accounts, your own retail prices and webhooks are not part of it. If your panel needs one of those, it needs a process around the API, not another call.

On the supplier side, the panel's own client uses the same shape: a POST to the supplier's API path with a key and an action, form-encoded, JSON back. The path is /api/v2, the timeout is 30 seconds, redirects are not followed, and the client does not retry an add. Those choices are about not sending the same order twice. A redirect could carry the key to another host, and a retry could create a duplicate order.

The four calls

ActionParametersReturnsWhat to store
servicesNoneArray of service objectsThe service id, name, rate, minimum and maximum
balanceNoneBalance and currencyThe balance and the time you read it
addservice, link, quantityAn order idThe public order id and the request you sent
statusorderCharge, start count, status, remainsThe state, the remains and the last change time

The four actions on the public API. A client that stores the bold fields can render an order page without another call.

Call one: services

The services action returns an array. Each item carries the service id, the name, a type label, the category, the rate, the minimum, the maximum and three flags: refill, cancel and drip feed. The rate is a string with four decimals, and the minimum and maximum are integers.

Parse the rate as a decimal, not a float. A float loses precision at the fourth decimal, and a price comparison built on floats can disagree with the ledger by a cent. The type field is a fixed label on every row, so use the category and the flags for filtering rather than the type.

Cache the catalogue with the time you read it. Service ids can change when a supplier re-imports its list, and a cached id that no longer exists produces an "Incorrect service ID" error at the add step. Refresh the cache on a schedule and keep the service name next to the id so a missing row is visible in your own logs.

Call two: balance

The balance action returns the wallet balance and the currency. The balance is a string with two decimals. Read it before an add call when the order size is close to the balance, because an add that cannot be paid for returns an error rather than a queued order on the public API.

The balance is not the same as the supplier's balance. The public API reports your wallet with this panel. The panel's own supplier balance is internal, and a shortfall there produces a queued order rather than an API error. That distinction matters when you debug: an add that succeeds and a status that says Queued is a panel-side funds queue, not a problem with your key.

Store the balance with a timestamp. A balance without a time is a number without a context, and a reseller dashboard that shows a stale balance is worse than one that shows the time it was read.

Call three: add

The add action takes the service id, the link and the quantity. It validates that the service exists and is active, that the quantity is inside the minimum and maximum, and that the link is present and not too long. It then places the order and returns the public order id.

The public id is the string your customer sees. It is not the supplier's order id. Store it as the primary reference for support, for the status call and for the wallet entry. A supplier id from another system will be rejected by the status call, and so will an order that belongs to a different key.

Do not retry an add blindly after a timeout. The first call may have reached the panel and created an order even though your client did not see the response. A retry with the same link and service is caught by the active-order check and stored as a queued order, not sent twice to the supplier. That is safer than a duplicate, but it still leaves you with two orders and one delivery. Read the orders list or ask support before you retry.

The add call also returns errors as JSON. An invalid service, an out-of-range quantity, a low balance and a link problem all arrive as an error object. Your client should show the error text to the operator and keep the request in a log with the time, the service id, the link and the quantity.

Call four: status

The status action takes the public order id and returns the charge, the start count, the status label and the remains. The charge has four decimals. The start count and the remains are strings, so parse them as integers before you compare them.

The status is a human label, not an internal enum. The labels are Pending, Placing, Queued, In progress, Completed, Partial, Canceled and Refunded. Two internal states share the Queued label, so a client that needs to tell a funds queue from a same-link queue has to read the order events, not only the status.

LabelWhat it means for your clientNext call
PendingThe order exists and is waiting to be placedStatus again after a short wait
PlacingThe panel is confirming with the supplierStatus again, with backoff
QueuedThe order is waiting for funds or for an earlier orderStatus and the order events
In progressThe supplier accepted and the count can moveStatus for remains
CompletedThe supplier reports the full quantityStop polling, keep the record
PartialThe supplier delivered less than orderedRead the remains and the wallet credit
CanceledThe order stopped before deliveryCheck the refund entry
RefundedThe charge returned to the walletStop polling, keep the record

The labels are the ones the public API returns. A client should map them explicitly and keep the raw label in its log.

Poll on a schedule you can justify, and back off when the status does not change. The panel writes a repeated waiting event at most once per 30 minutes, so a status call every second adds load without adding information. A slower poll with a longer backoff after several unchanged answers is easier on both sides.

The error that looks like success

The public API returns errors in the JSON body, often with an HTTP 200. A client that checks only the status code will treat an error object as a successful response and then fail on a missing field. Check the error key first, before you parse the payload.

The error strings are specific: an incorrect key, an incorrect service id, an incorrect order id, an invalid action, a quantity outside the range, a link that is empty or too long. Show the string to the operator and log the request. A generic "request failed" message hides the one fact that would fix the call.

The supplier side has the same pattern. The panel's client checks the error field in the supplier response, scrubs the key from the text, and caps the message at 240 characters. The cap keeps a long supplier error from filling a log line, and the scrub keeps the key out of the log. A client that copies supplier errors into its own UI should do the same.

A worked example: the four calls in sequence

A minimal integration reads the catalogue once, reads the balance before an order, places the order, then polls the status until a final label. The sequence is short enough to write on one page:

  1. Call services and cache the ids, rates, minimums and maximums with a timestamp.
  2. Call balance and compare it with the order cost before you place anything.
  3. Call add with a valid service, a public link and a quantity inside the range.
  4. Store the public order id, then call status until the label is final.
  5. On partial, read the remains and the wallet credit. On canceled or refunded, check the refund entry.

Everything else is a view. A reseller dashboard is a table over the stored orders. A status page is a count over the same rows. A support ticket is a pointer to one public id. The four calls are the only place where the state enters your system.

What the four calls do not cover

Refill and cancel are not public actions. If your panel needs them, the request goes through support or through a process you build around the API. The same is true for sub-accounts, your own retail prices inside this panel, webhooks and a white-label storefront. The reseller page lists those as roadmap items, not shipped features, and a client that assumes them will be waiting for a call that does not exist.

The four calls also do not push. There is no webhook, so the status call is the only way to learn that an order changed. A client that polls on a schedule and stores the last change time can reconstruct the timeline. A client that waits for a push waits forever.

What to do next

If your add call returns an error with an HTTP 200, check the error key first. If the key is valid, check the service id against a fresh services call, then the quantity against the minimum and maximum. If all three are correct, read the balance.

If your status call rejects an order id, check that you are using the public id from add, not a supplier id, and that the key belongs to the account that placed the order. An order id from another account is rejected on purpose.

If your client sees Queued and cannot tell why, read the order events. The status label collapses two queues into one word, and the event text names the cause. A client that stores the events can show the difference; a client that stores only the label cannot.

For the exact request and response fields, open the API documentation. For the queue behind a Queued label, read order queues. For live availability, open the status page, and for a key or a limit question, use the support page.

Common questions

What does the services action return?

An array of objects with the service id, name, type, category, rate, minimum, maximum and the refill, cancel and drip-feed flags. The rate is a string with four decimals. Parse it as a decimal, not a float, if you compare prices or store it in a ledger.

Why does add return an order id that status rejects?

The add action returns the public order id, the short string the customer sees. The status action expects that same public id and checks that the order belongs to the key that asks. A supplier id from another system will be rejected, and so will an order that belongs to a different account.

Does the API push status changes?

No. This API has no webhook. Your panel polls status for each open order, which is why the status response includes remains and start_count: one call gives you both the state and the numbers you need to display.

The numbers used on this page

Show all 10 figures and where they come from

Every figure below is read from the Talon database when this page is rendered. Market figures come from the crawl finished on 7 November 2026. Prices are per 1,000 units in USD.

ItemValue
Panels in the market crawl32
Products in the market table8,755
Minimum gap between repeated waiting events, in minutes30
Supplier API path/api/v2
Supplier API timeout, in seconds30
Maximum supplier error length kept, in characters240
Order states treated as open6
Supplier status spellings mapped to internal states13
Supplier cancel replies treated as success5
Actions on the public API4