Give your resellers an API of their own.
Every GsmWhale shop exposes one order endpoint. Your clients point their existing software at your domain, authenticate with a JWT or a legacy key, and it works — place an order, poll its status, read the result. No adapter to write on either side.
curl -X POST 'https://your-domain.com/api/v1/orders' \
-H 'Authorization: Bearer <JWT>' \
-H 'Content-Type: application/json' \
-d '{"action":"placeimeiorder","parameters":{"id":42,"imei":"352099001761481","qnt":1}}'
Every order moves through the same rail.
Place it, poll it, read the result. The status values are stable across all three API styles — build one state machine and it works everywhere.
Pending
Waiting for processing
Processing
Validated, queued, running
In Progress
Service executing
Completed
Code / reply delivered
Partial
One result delivered
Failed
Service returned an error
Rejected
Order denied
Refunded
Credit returned to wallet
One signed token drives the whole rail.
The JWT Auth Engine verifies every JSON call — HS256 signature, 15-minute expiry, scoped claims — then walks the order rail from place to reply. No adapter, one header.
JWT Auth Engine
hs256 · scope · rail
PendingIn ProgressSuccess
Four order actions, every one verified.
The engine checks the token once, then picks the right scope — place, bulk, poll.
-
Authorization: Beareron every request -
HS256signature, 15-minute expiry, silent refresh -
Scoped tokens from
Settings → API Keys -
REST mirrors:
account·products·order
placeimeiorder
Submit a single order line with IMEI + fields.
placeimeiorderbulk
Batch submit many lines in one call.
getimeiorder
Poll a single order for status and result.
getimeiorderbulk
Poll many orders in one request.
{ "ORDER": { "ORDERID": "4821", "STATUS": "Pending", "REPLY": null } }
curl -X POST 'https://your-domain.com/api/v1/orders' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1Ni...' \
-H 'Content-Type: application/json' \
-d '{"action":"placeimeiorder","parameters":{"id":42,"imei":"352099001761481","qnt":1}}'
placeimeiorder
placeimeiorderbulk
getimeiorder
getimeiorderbulk
The relay your legacy software already speaks.
The Form Relay accepts the Dhru Fusion v6.1 action set over form-encoded POSTs, keeps the XML parameter payload as-is, and walks it onto the same order rail. Switch keys, not code.
Six actions. One form. No SDK.
Authenticate with username + apiaccesskey, pick
requestformat=JSON, and the action field shapes the call.
- All 6 Dhru Fusion v6.1 actions supported
- Single and bulk submit for Fusion 31–59 APIs
-
XML
parameterspayload kept as-is - Reseller keys swap in without code changes
accountinfo
Balance and currency for the key.
imeiservicelist
Service list (same as server service list).
placeimeiorder
Place a single order line.
placeimeiorderbulk
Batch submit many lines in one call.
getimeiorder
Order details — status, reply, date.
getimeiorderbulk
Batch poll many orders in one request.
{ "ORDER": { "ORDERID": "4821", "STATUS": "Pending" } }
{ "ERROR": [ { "MESSAGE": "Validation failed" } ] }
$data = [
'username' => 'client_42',
'apiaccesskey' => 'YOUR_API_ACCESS_KEY',
'requestformat' => 'JSON',
'action' => 'placeimeiorder',
'parameters' => '<PARAMETERS><IMEI>352099001761481</IMEI>'
. '<ID>42</ID><QNT>1</QNT></PARAMETERS>'
];
$ch = curl_init('https://your-domain.com/api/index.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
$response = json_decode(curl_exec($ch), true);
echo "Order id: " . $response['ORDER']['ORDERID'];
<PARAMETERS> <IMEI>352099001761481</IMEI> <ID>42</ID> <QNT>1</QNT> <CUSTOMFIELD>eyJtb2RlbCI6IlNNLUE1MzUifQ==</CUSTOMFIELD> </PARAMETERS>
accountinfo
imeiservicelist
placeimeiorder
placeimeiorderbulk
getimeiorder
getimeiorderbulk
PHP Form Relay
form · xml · rail
PendingIn ProgressSuccess
A typed shim between your scripts and the rail.
The FastAPI shim runs as an httpx client: POST the order, poll the status
forward, read the typed reply — in one small loop, no hidden state.
FastAPI shim
httpx · typed · rail
PendingIn ProgressSuccess
Place, poll, read — the whole loop.
One typed httpx client walks the full lifecycle —
non-2xx raises, poll until the status settles.
-
All 6 actions via
httpx+ the bearer token -
raise_for_status()on every non-2xx call -
Poll every
3suntilCompleted / Failed / Rejected
accountinfo
Balance and currency for the key.
imeiservicelist
Service list (same as server service list).
placeimeiorder
Place a single order line.
placeimeiorderbulk
Batch submit many lines in one call.
getimeiorder
Order details — status, reply, date.
getimeiorderbulk
Batch poll many orders in one request.
{
"ORDER": {
"ORDERID": "4821",
"STATUS": "Completed",
"REPLY": "29% © 100% Complete"
}
}
import httpx, time
API = "https://your-domain.com/api/v1/orders"
TOKEN = "eyJhbGciOiJIUzI1Ni..." # Bearer token from Settings → API Keys
def place_order(price_id: int, imei: str) -> dict:
r = httpx.post(
API,
headers={"Authorization": f"Bearer {TOKEN}"},
json={"action": "placeimeiorder",
"parameters": {"id": price_id, "imei": imei, "qnt": 1}},
timeout=30,
)
r.raise_for_status()
return r.json()["ORDER"]
def wait_status(order_id: str) -> dict:
while True:
r = httpx.get(
API,
params={"action": "getimeiorder", "order_id": order_id},
headers={"Authorization": f"Bearer {TOKEN}"},
)
order = r.json()["ORDER"]
if order["STATUS"] in ("Completed", "Failed", "Rejected"):
return order
time.sleep(3)
accountinfo
imeiservicelist
placeimeiorder
placeimeiorderbulk
getimeiorder
getimeiorderbulk
The raw endpoint. One JSON rail.
REST Core takes Bearer-authenticated JSON against POST /api/v1/orders —
the same order rail the other three engines ride, exposed raw.
Mirrors, typed like the engines.
Bearer-authenticated JSON against four REST mirrors — account, products, orders and order — sharing one typed reply shape.
-
Authorization: Bearerheader on every call - JSON in, JSON out — no XML parameters here
-
Typed replies —
ORDER/ERRORsettle by status -
Mirrors we host:
account·products·orders
action
string
placeimeiorder · placeimeiorderbulk · getimeiorder · getimeiorderbulk
parameters.id
int
service / price id from the products mirror
parameters.imei
string
device IMEI to activate
parameters.qnt
int
quantity, defaults to 1
/api/v1/account
Balance and currency for the key.
/api/v1/products
Service list as JSON rows.
/api/v1/orders
Place an order — single or bulk.
/order?order_uuid=
Poll a single order — status + reply.
{ "ORDER": { "ORDERID": "4821", "STATUS": "Pending", "REPLY": null } }
{ "ERROR": [ { "MESSAGE": "Validation failed" } ] }
curl -X POST 'https://your-domain.com/api/v1/orders' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1Ni...' \
-H 'Content-Type: application/json' \
-d '{"action":"placeimeiorder","parameters":{"id":42,"imei":"352099001761481","qnt":1}}'
curl -X GET 'https://your-domain.com/api/v1/order?order_uuid=4821' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1Ni...'
# → { "ORDER": { "ORDERID": "4821", "STATUS": "In Progress", "REPLY": "29% © 100% Complete" } }
account
products
orders
order
Bearer auth, JSON only — the same order rail, unmediated.
REST Core
bearer · json · rail
Every supplier API you already use, wired in.
Pick a provider to see how GsmWhale talks to its API — supported actions, delivery model and the quick links to manage the connection.
Click any provider to see integration details on the right.
Orders
Balance
Success
Latency
Protocol:
Currency:
Services:
Auto delivery:
Setup time:
Actions map 1:1 to orders routed through this provider across GsmWhale's JWT, PHP and Python clients.
Failures come back in one shape.
A bad key, an unknown action, a service the account cannot order, or not enough credit — every failure returns a consistent message, whatever the API style.
{
"ERROR": [
{ "MESSAGE": "Validation failed" }
]
}
Wrap every call so a non-2xx status raises before you read the body. The MESSAGE is always human-readable and stable across releases.
The full reference lives in the knowledge base.
Field-by-field responses, every status value an order can hold, and worked examples — and your resellers can read them without an account.
