Knox Wizard Partner API
The Partner API lets approved resellers and distributors sell Knox Wizard licenses automatically from their own website, shop or bot: create a customer account, then activate or renew its license. Every activation is paid from your prepaid credit balance.
Authentication
Base URL:
https://api.knoxwizard.com/partner/v1
Send your API key on every request as a bearer token (or an X-API-Key header):
Authorization: Bearer kw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
Rate limit: 120 requests per minute per key. Requests and responses are JSON.
Plans & prices
| Plan | Duration | Reseller | Distributor |
|---|---|---|---|
3m | 3 months | $20 | $15 |
6m | 6 months | $25 | $20 |
12m | 12 months | $30 | $25 |
Your account type decides your price. GET /plans always returns your current prices. Activating on an account that is still active adds the time on top of the remaining time.
Recommended flow
- Your customer pays you.
- New customer:
POST /accountswith their email andplan. The account is created and licensed in one step.
Existing customer (renewal):POST /licenses/activatewith their email andplan. - Always send your order number as
reference. If a request times out, retry with the same reference; you are never charged twice. - Give the customer their login (email + password) and the download link knoxwizard.com. Sign-in codes are emailed, so the email must be real. Customers can change their password with "Forgot password" in the app.
Creating an account without a plan is free: it is created expired (no access) and can be activated later.
Balance
{ "ok": true, "partner": { "id": "…", "type": "reseller", "name": "Acme GSM", "email": "[email protected]", "company": "" },
"balance": 270, "currency": "USD" }
Plans
{ "ok": true, "type": "reseller", "currency": "USD", "balance": 270,
"plans": [ { "plan": "3m", "label": "3 Months", "months": 3, "cost": 20 },
{ "plan": "6m", "label": "6 Months", "months": 6, "cost": 25 },
{ "plan": "12m", "label": "12 Months", "months": 12, "cost": 30 } ] }
Create an account
| Field | Required | Description |
|---|---|---|
email | yes | Customer's real email (login + sign-in codes). |
password | no | Min 6 characters. If omitted, a password is generated and returned once as password. |
plan | no | 3m, 6m or 12m: create and license (charged). Omit for a free expired account. |
reference | recommended | Your order ID (1–64 chars: letters, digits, . _ : -). |
POST /partner/v1/accounts
{ "email": "[email protected]", "plan": "3m", "reference": "ORD-10045" }
201 Created
{ "ok": true,
"account": { "email": "[email protected]", "status": "active", "expiry": "2026-12-27",
"days_left": 92, "licensed": true, "devices_used_30d": 0 },
"password": "k7QmZ2xR9p",
"charge": { "plan": "3m", "cost": 20, "reference": "ORD-10045", "transaction_id": "…", "created_at": 1790500000 },
"balance": 250 }
409 account_exists means the email is already registered. Activate it instead. With 402 insufficient_credits nothing is created.
Activate / renew a license
Works on any Knox Wizard customer account (renewals of accounts created elsewhere too).
POST /partner/v1/licenses/activate
{ "email": "[email protected]", "plan": "12m", "reference": "ORD-10046" }
200 OK
{ "ok": true,
"account": { "email": "[email protected]", "status": "active", "expiry": "2027-12-27", "days_left": 457, "licensed": true, … },
"charge": { "plan": "12m", "cost": 30, "reference": "ORD-10046", … },
"balance": 220 }
Look up an account
Only accounts you created or licensed are visible; others return 404.
Transaction history
Your credit ledger, newest first. type: topup, deduct, charge, refund; amount is signed.
Idempotency
A reference is charged at most once. Sending it again, even at the same moment, returns the original result with "idempotent_replay": true and no new charge.
Errors
Errors return "ok": false, a machine-readable code and a readable error. A failed request is never charged.
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_plan | Unknown plan code. |
| 400 | invalid_email / invalid_password | Bad email, or password shorter than 6. |
| 400 | invalid_reference / invalid_body | Bad reference, or body is not a JSON object. |
| 401 | invalid_api_key | Missing, wrong or revoked key. |
| 402 | insufficient_credits | Top up. Response includes balance and cost. |
| 403 | partner_disabled / ip_not_allowed | Access suspended, or IP not in your allowlist. |
| 403 | account_disabled | The customer account is blocked by support. |
| 404 | account_not_found | No such account (or not visible to you). |
| 409 | account_exists | Email already registered. Activate it instead. |
| 429 | rate_limited | Slow down. |
| 500 | server_error | Temporary; retry with the same reference. |
Examples
cURL
curl -X POST https://api.knoxwizard.com/partner/v1/accounts \
-H "Authorization: Bearer $KW_API_KEY" -H "Content-Type: application/json" \
-d '{"email":"[email protected]","plan":"3m","reference":"ORD-10045"}'
PHP
<?php
function kw_api(string $method, string $path, ?array $body = null): array {
$ch = curl_init('https://api.knoxwizard.com/partner/v1' . $path);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('KW_API_KEY'), 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => $body ? json_encode($body) : null,
]);
$res = json_decode(curl_exec($ch), true) ?: ['ok' => false, 'error' => curl_error($ch)];
curl_close($ch);
return $res;
}
$order = ['email' => $email, 'plan' => '3m', 'reference' => 'ORD-' . $orderId];
$res = kw_api('POST', '/accounts', $order);
if (!$res['ok'] && ($res['code'] ?? '') === 'account_exists') {
$res = kw_api('POST', '/licenses/activate', $order); // renewal
}
Node.js
const kw = (method, path, body) => fetch(`https://api.knoxwizard.com/partner/v1${path}`, {
method, headers: { Authorization: `Bearer ${process.env.KW_API_KEY}`, "Content-Type": "application/json" },
body: body ? JSON.stringify(body) : undefined
}).then(r => r.json());
let r = await kw("POST", "/accounts", { email, plan: "12m", reference: `ORD-${orderId}` });
if (!r.ok && r.code === "account_exists") r = await kw("POST", "/licenses/activate", { email, plan: "12m", reference: `ORD-${orderId}` });
Python
import os, requests
def kw(method, path, body=None):
return requests.request(method, f"https://api.knoxwizard.com/partner/v1{path}",
headers={"Authorization": f"Bearer {os.environ['KW_API_KEY']}"}, json=body, timeout=30).json()
print(kw("GET", "/me")["balance"])
Questions? Contact Knox Wizard support. © Knox Wizard