Whozex Reseller API

Full-stack reseller API to manage sub-users, proxy packages, balances, and webhooks — designed for Telegram bots, custom dashboards, and automation.

Base URL
https://api.whozex.com/v1
API Version
v1.0.0

Authentication

All API requests require a valid API key. API access is granted by admin and cannot be self-registered.

🔑
Your API key is available in your Dashboard → API section once access is enabled by an administrator.

Using Your Key

Pass your API key in one of two ways:

Option 1 — Authorization Header (recommended)
Authorization: Bearer wx_live_your_api_key_here
Option 2 — X-API-Key Header
X-API-Key: wx_live_your_api_key_here
cURL Example
curl -H "Authorization: Bearer wx_live_your_api_key_here" \
     https://api.whozex.com/v1/account

Base URL & Versioning

All endpoints are prefixed with the version path:

https://api.whozex.com/v1/

The API uses URL versioning. Future breaking changes will be released under /v2/, giving time for migration.

Standard Response Format

All responses follow a consistent envelope:

Success Response
{
  "success": true,
  "data": { /* endpoint-specific payload */ },
  "meta": {
    "timestamp": "2025-01-01T12:00:00.000Z",
    "version": "1.0.0"
  }
}
Error Response
{
  "success": false,
  "error": {
    "code":    "INSUFFICIENT_BALANCE",
    "message": "User balance ($5.00) is insufficient. Cost: $20.00"
  },
  "meta": { /* ... */ }
}

Paginated endpoints return a pagination object inside data:

"pagination": {
  "total": 47, "page": 1, "limit": 20,
  "pages": 3, "has_next": true, "has_prev": false
}

Error Codes

Code
HTTP
Description
MISSING_API_KEY
401
No API key provided in the request
INVALID_API_KEY
401
Key does not exist or has been revoked
API_DISABLED
403
API access disabled for this account
NOT_FOUND
404
Resource not found or not owned by you
MISSING_FIELD
400
Required field missing in request body
INVALID_PARAMS
400
Invalid parameter value
EMAIL_TAKEN
409
Email already registered
INSUFFICIENT_BALANCE
402
User balance too low for operation
INSUFFICIENT_RESELLER_BALANCE
402
Your balance too low to fund user
PROVIDER_ERROR
502
Proxy provider API error
WEBHOOK_LIMIT
422
Maximum 10 webhooks reached

Rate Limits

Requests are rate-limited per API key. Stay well within limits for production use.

TierLimitWindow
Standard300 requestsPer minute
Write ops (POST/PATCH/DELETE)60 requestsPer minute
⚠️
Package creation calls the proxy provider API — treat POST /users/:id/packages as a heavy operation. Cache results when possible.

GET /account

Returns your reseller account information, balance, and API key metadata.

GET/v1/account
curl -H "Authorization: Bearer $API_KEY" \
     https://api.whozex.com/v1/account
Response
{
  "success": true,
  "data": {
    "id": "...", "name": "Reseller Name", "email": "you@example.com",
    "balance": 150.00, "is_vip": true,
    "api_key": { "last_used_at": "2025-01-01T10:00:00Z" },
    "stats":   { "packages": 24, "sub_users": 8, "total_spent": 340.00 },
    "pricing": { "custom_price_per_gb": 0.90 }
  }
}

GET /account/stats

Detailed statistics including spending breakdown, GB breakdown by proxy type, and 30-day chart data.

GET/v1/account/stats
curl -H "Authorization: Bearer $API_KEY" \
     https://api.whozex.com/v1/account/stats

GET /account/transactions

Paginated transaction history for your reseller account.

GET/v1/account/transactions

Query Parameters

ParamTypeDefaultDescription
pageinteger1Page number
limitinteger20Items per page (max 100)
typestringFilter by: deposit, purchase, add_gb

POST /account/regenerate-key

Permanently revoke your current API key and generate a new one. All existing integrations will stop working immediately.

POST/v1/account/regenerate-key
⚠️
This action is irreversible. Update all integrations with the new key immediately.
curl -X POST \
     -H "Authorization: Bearer $API_KEY" \
     https://api.whozex.com/v1/account/regenerate-key

GET /users

List all sub-users you have created. Results are paginated.

GET/v1/users

Query Parameters

ParamTypeDefaultDescription
pageinteger1Page number
limitinteger20Max 100
searchstringSearch by name or email

POST /users

Create a new sub-user account. The account is automatically verified and ready to receive balance and packages.

POST/v1/users

Request Body

FieldTypeDescription
emailstringrequiredUser's email address (must be unique)
namestringoptionalDisplay name (defaults to email prefix)
notestringoptionalInternal note (not stored)
curl -X POST \
     -H "Authorization: Bearer $API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"name":"John Doe","email":"john@example.com"}' \
     https://api.whozex.com/v1/users
Response — 201 Created
{ "id": "uuid...", "name": "John Doe", "email": "john@example.com",
  "balance": 0.00, "package_count": 0, "created_at": "..." }

POST /users/:id/balance

Add or deduct balance for a sub-user. Adding balance deducts it from your reseller balance. Deducting returns it to you.

POST/v1/users/:id/balance

Request Body

FieldTypeDescription
actionstringrequired"add" or "deduct"
amountnumberrequiredAmount in USD (positive)
notestringoptionalAppears in transaction history
# Add $50 to a user (deducted from your balance)
curl -X POST \
     -H "Authorization: Bearer $API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"action":"add","amount":50,"note":"TRX payment received"}' \
     https://api.whozex.com/v1/users/USER_ID/balance
Response
{ "user_id": "...", "action": "add", "amount": 50.00,
  "user_balance": 50.00, "reseller_balance": 100.00 }

POST /users/:id/packages

Purchase a new proxy package for a sub-user. Balance is deducted from the sub-user's account. Your pricing (custom or VIP) is applied automatically.

POST/v1/users/:id/packages

Request Body

FieldTypeDescription
gbintegerrequiredAmount of GB to purchase (minimum 1)
proxy_typestringoptional"residential" (default), "datacenter", "mobile"
curl -X POST \
     -H "Authorization: Bearer $API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"proxy_type":"residential","gb":20}' \
     https://api.whozex.com/v1/users/USER_ID/packages
Response — 201 Created
{ "id": "PKG-A1B2C3", "proxy_type": "residential",
  "total_gb": 20, "used_gb": 0, "remaining_gb": 20,
  "status": "active",
  "evomi_username": "wx3f8a2c01",
  "evomi_password": "wxp1a2b3c4d5e6f7a8",
  "cost": 30.00, "price_per_gb": 1.50,
  "user_balance_after": 20.00,
  "created_at": "...", "expires_at": "..." }

GET /packages/:id

Fetch a single package with live GB data from the proxy provider. The remaining_gb field reflects actual current balance. live: true confirms real-time data.

GET/v1/packages/:id
curl -H "Authorization: Bearer $API_KEY" \
     https://api.whozex.com/v1/packages/PKG-A1B2C3

POST /packages/:id/add-gb

Add GB to an existing package. Balance is deducted from the package owner's account. GB is added additively on the provider.

POST/v1/packages/:id/add-gb

Request Body

FieldTypeDescription
gbintegerrequiredGB to add (minimum 1)
notestringoptionalAppears in transaction log
curl -X POST \
     -H "Authorization: Bearer $API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"gb":10}' \
     https://api.whozex.com/v1/packages/PKG-A1B2C3/add-gb

GET /packages/:id/credentials

Get formatted proxy connection strings with optional country/city targeting.

GET/v1/packages/:id/credentials

Query Parameters

ParamTypeDescription
countrystring2-letter ISO code (e.g. US, DE, TR). Use any for random.
citystringCity name (e.g. Istanbul)
# Get Turkish proxies
curl -H "Authorization: Bearer $API_KEY" \
     "https://api.whozex.com/v1/packages/PKG-A1B2C3/credentials?country=TR"
Response
{ "username": "wx3f8a2c01", "password": "wxp1a2b3...",
  "http": {
    "host": "rp.evomi.com", "port": 1000,
    "connection_string": "rp.evomi.com:1000:wx3f8a2c01:wxp1a2b3..._country-TR",
    "curl_example": "curl -x \"http://wx3f8a2c01:wxp1a2b3..._country-TR@rp.evomi.com:1000\" https://ip.whozex.com"
  },
  "socks5": { "host": "rp.evomi.com", "port": 1002, "connection_string": "..." },
  "targeting": { "country": "TR", "city": null }
}

GET /packages/:id/usage

Usage history from the proxy provider, suitable for charts.

GET/v1/packages/:id/usage

Query Parameters

ParamDefaultDescription
duration7dTime range: 1d, 7d, 30d, etc.
granularitydayminute, hour, or day

GET /pricing

Returns all pricing tiers with your effective price per GB (custom, VIP, or standard).

GET/v1/pricing
Response
{ "is_vip": true, "custom_price_per_gb": 0.90,
  "plans": [
    { "gb": 10,  "label": "10 GB",  "standard_price": 2.00, "vip_price": 1.60, "your_price": 0.90, "total_cost": 9.00 },
    { "gb": 100, "label": "100 GB", "standard_price": 1.00, "vip_price": 0.80, "your_price": 0.90, "total_cost": 90.00 }
  ]
}

GET /pricing/calculate

Calculate exact cost for any GB amount before purchasing.

GET/v1/pricing/calculate?gb=50
curl -H "Authorization: Bearer $API_KEY" \
     "https://api.whozex.com/v1/pricing/calculate?gb=50"
Response
{ "gb": 50, "price_per_gb": 0.90, "total": 45.00, "is_vip": true, "custom_price": true }

GET /analytics/overview

High-level analytics across all your sub-users: balances, package counts, spending, and 30-day chart data.

GET/v1/analytics/overview
curl -H "Authorization: Bearer $API_KEY" \
     https://api.whozex.com/v1/analytics/overview

POST /webhooks

Register a webhook URL to receive real-time events. Max 10 webhooks per account.

POST/v1/webhooks

Request Body

FieldTypeDescription
urlstringrequiredHTTPS endpoint to receive events
eventsstring[]requiredArray of event names to subscribe to
curl -X POST \
     -H "Authorization: Bearer $API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"url":"https://bot.example.com/webhook","events":["package.low_gb","balance.added","user.created"]}' \
     https://api.whozex.com/v1/webhooks
Response — 201 Created
{ "id": "WH-A1B2C3D4", "url": "https://bot.example.com/webhook",
  "events": ["package.low_gb", "balance.added"],
  "secret": "wxsec_a1b2c3...",
  "note": "Save the secret — it will not be shown again." }
🔒
The webhook secret is shown only once on creation. Store it securely for signature verification.

Webhook Events

Subscribe to any combination of these events when creating a webhook:

package.createdNew package purchased for a sub-user
package.low_gbPackage GB fell below threshold (via cron)
package.expiredPackage deleted or expired
package.gb_addedGB added to a package
balance.addedBalance added to a sub-user
balance.deductedBalance deducted from a sub-user
refill.successAuto-refill completed successfully
refill.failedAuto-refill failed (insufficient balance)
user.createdNew sub-user created via API
user.deletedSub-user deleted

Event Payload

{
  "event":     "package.created",
  "data":      { "user_id": "...", "package_id": "PKG-...", "gb": 20, "cost": 30.00 },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

Signature Verification

Every webhook request includes an X-Whozex-Signature header. Verify it to ensure the payload is authentic.

Node.js / TypeScript
import crypto from "crypto";

function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

// Express handler example
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const sig    = req.headers["x-whozex-signature"] as string;
  const secret = process.env.WEBHOOK_SECRET;
  if (!verifyWebhook(req.body.toString(), sig, secret)) {
    return res.status(401).send("Invalid signature");
  }
  const event = JSON.parse(req.body.toString());
  console.log("Event:", event.event, event.data);
  res.sendStatus(200);
});
Python
import hmac, hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

# Flask handler example
@app.route("/webhook", methods=["POST"])
def webhook():
    sig    = request.headers.get("X-Whozex-Signature", "")
    secret = os.environ["WEBHOOK_SECRET"]
    if not verify_webhook(request.data, sig, secret):
        abort(401)
    event = request.get_json(force=True)
    print("Event:", event["event"], event["data"])
    return "", 200

Whozex Reseller API v1.0.0

© 2025 Whozex. All rights reserved.

Get your API key →