Reseller APIv1
Ctrl K
Run in PostmanOpenAPI spec Checking…

Wholesale Reseller API

This API lets wholesale proxy resellers buy and manage shared proxies programmatically — using the same engine and pricing our store uses, plus a fixed per-reseller discount. Every request runs through the exact same purchase engine that manual orders use.

Quick start

  1. Create an account and contact support to enable reseller mode and set your discount.
  2. Get your API key from support.
  3. Use the endpoints below — each operation has its own HTTP method and path.
  4. Top up your balance — each purchase or extension is debited from it.

Base URL & authentication

All paths under /api/reseller/v1/* require the X-API-Key header. Keep your key secret — any request with an invalid key is rejected with 401.

Important — every operation has a specific HTTP method. Make sure your client sends the right one: GET to read, POST to create, PATCH to update, DELETE to remove. Sending GET to a POST path returns the list instead of creating a unit.
HeadersCopied!
Base URL: https://wtproxy.com
Header: X-API-Key: <your API key>
Content: Content-Type: application/json
OpenAPI: https://wtproxy.com/api/reseller/v1/openapi.json

Period values

The "period" field accepts five values: 3h (3 hours), 12h (12 hours), 24h (a day), 7d (a week), 30d (a month).

Allowed valuesCopied!
{
"period": "3h"
// or: "12h" | "24h" | "7d" | "30d"
}

Pricing & discount

Prices returned by /pools are the final, post-discount prices — exactly what is debited. For create and extend the amount is debited before execution and fully auto-refunded on failure.

After-discount exampleCopied!
{
"3h": 0.32,
"12h": 0.56,
"24h": 1.04,
"7d": 5.60,
"30d": 20.00
}

Webhook setup (step-by-step)

Webhooks notify your app of every account event (unit created / extended / released / swapped, usage warning, throttle, unit down, balance low). Setup happens through the API itself:

  1. Stand up a public HTTPS endpoint on your server that accepts a JSON POST.
  2. Call PATCH /api/reseller/v1/webhook with { "url": "<your endpoint>" }. The response includes a secret — store it immediately (not shown again).
  3. On every incoming request: verify the X-WTProxy-Signature header using HMAC-SHA256 of the raw body with the secret. Reject anything that doesn't match.
  4. Return 2xx fast (< 5s). Any error or timeout schedules an exponential retry (1m → 5m → 30m → 2h → 6h, up to 6 attempts).
  5. Inspect the delivery log via GET /api/reseller/v1/webhook/deliveries — shows every event's status (delivered/pending/failed) and reason.

The events your endpoint will receive:

EventFires whenKey data fields
unit.createdA unit is purchasedproxyRef, poolId, period, pricePaid
unit.extendedA unit is extendedproxyRef, period, pricePaid, expiresAt
unit.swappedA unit is moved to another serverproxyRef
unit.protocol_changedProtocol/encryption changedproxyRef
unit.modifiedCredentials/whitelist modifiedproxyRef
unit.releasedA unit is releasedproxyRef
unit.downA unit stops unexpectedly: data cap or server unreachableproxyRef, reason (quota_exceeded | server_unreachable)
usage.warning80% throttle / 75% delete of the daily capproxyRef, kind, thresholdPct, consumedMb, limitMb
usage.throttledA unit is speed-limited for exceeding dataproxyRef, throttleSpeedMbps, durationHours, consumedMb, limitMb
server.downAdmin flagged a whole server as downpoolCode, reason, affectedUnits[]
server.ip_changedServer host IP changed (redeploy)poolCode, newIp, oldIp?, affectedUnits[]
balance.lowYour wallet drops below the thresholdbalance, threshold

Every payload has the shape { event, occurredAt, data }. The fields under data are shown above.

Headers sent with every webhook:

  • X-WTProxy-Event
    Event name, e.g. unit.created.
  • X-WTProxy-Delivery
    Unique delivery id per attempt (use for idempotency on your side).
  • X-WTProxy-Timestamp
    Send time (unix seconds).
  • X-WTProxy-Signature
    sha256=<HMAC of body with secret>. Verify before trusting the payload.

Node.js verification example:

import crypto from 'crypto';

app.post('/wtproxy-events', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.header('X-WTProxy-Signature') || '';
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.WTPROXY_WEBHOOK_SECRET)
    .update(req.body)            // raw body, before JSON.parse
    .digest('hex');
  if (sig !== expected) return res.sendStatus(401);

  const event = JSON.parse(req.body.toString());
  // event = { event: 'unit.created', occurredAt: '...', data: {...} }
  res.sendStatus(200);            // ack within 5s
});

Connection fields — what they mean

  • ip
    The proxy IP address the client connects to.
  • port
    The port number used for the connection.
  • username
    The username for proxy authentication.
  • password
    The password for proxy authentication.
  • protocol
    Protocol: socks5 / http / inject — where inject = HTTP No Auth via IP whitelist.
  • poolId
    Pool (server) ID, e.g. "US-12".
  • provider
    The network provider, e.g. T-Mobile.
  • proxyRef
    The unique proxy reference in the form "PRX-{n}".
  • expiresAt
    Expiry date & time (ISO 8601).
Connection stringCopied!
203.0.113.45:51234:u_xxx:p_xxx

Pagination

Endpoints that return large lists (e.g. /units) are paginated. Items come under "data"; paging metadata under the "pagination" object. Control it with the page and pageSize query parameters.

  • page
    Current page number (1-based).
  • pageSize
    Items per page (default 50, max 200).
  • totalItems
    Total number of items across all pages.
  • totalPages
    Total number of pages = ceil(totalItems / pageSize).
  • hasNext
    true if a next page exists.
  • hasPrev
    true if a previous page exists.
RequestCopied!
GET /api/reseller/v1/units?page=2&pageSize=20
ResponseCopied!
{
"data": [ /* … units … */ ],
"pagination": {
"page": 2, "pageSize": 20,
"totalItems": 47, "totalPages": 3,
"hasNext": true, "hasPrev": true
}
}

Error handling

Every error returns a uniform "error" object. Branch on error.type and error.code (both stable, machine-readable); error.message is for display only. Each error carries a requestId — quote it when contacting support.

  • authentication_error401
    Missing or invalid API key.
  • permission_error403
    The account lacks reseller permission.
  • invalid_request_error400
    A malformed body, field, or value.
  • not_found_error404
    The requested resource does not exist.
  • insufficient_balance_error402
    Balance below the required amount (see error.required).
  • rate_limit_error429
    Request rate limit exceeded.
  • service_error⁨5xx⁩
    A temporary service error — retry.
ResponseCopied!
{
"error": {
"type": "insufficient_balance_error",
"code": "insufficient_balance",
"message": "Your balance is below the required amount.",
"documentationUrl": "https://wtproxy.com/api-docs#errors",
"requestId": "req_01HQX9ABCDEF"
}
}

Rate limits

Each key has two budgets: an account-wide one for the whole API, and a tighter one on a few heavy endpoints. They are independent — exhausting an endpoint’s budget does not block the others. Over the limit the API returns 429 with error.code = rate_limited and a Retry-After header: wait that long rather than retrying immediately.

  • Whole API (per key)120 / min
    The account-wide budget for any /api/reseller/v1 request.
  • GET /me/uptime10 / min
    Its own budget: one call aggregates thousands of probe readings. Exceeding it does not block the rest of the API.

Headers on every response

  • X-RateLimit-Limit
    The ceiling for the current window.
  • X-RateLimit-Remaining
    How many requests you have left in this window.
  • X-RateLimit-Reset
    When the window resets (unix seconds).
  • Retry-After
    On 429 only: how many seconds to wait before retrying.
Response headersCopied!
HTTP/1.1 200 OK
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 1785495600
ResponseCopied!
{
"error": {
"type": "rate_limit_error",
"code": "rate_limited",
"message": "Too many requests. Limit is 120 per minute. Retry after 24s.",
"requestId": "req_01HQX9ABCDEF"
}
}

Changelog

The most recent additions to the API. Additions are always backwards-compatible: new fields may appear in responses, so make your parser ignore what it does not recognise.

  • 2026-07-31
    New: GET /me/uptime — account-wide uptime with a per-unit breakdown (10 req/min).
  • 2026-07-31
    Documented: GET /countries and GET /states were live but undocumented — both are now here.
  • 2026-07-31
    Documented: a Rate limits section with the real numbers and headers, and {proxyRef} unified across every path example.
Newest endpointCopied!
curl 'https://wtproxy.com/api/reseller/v1/me/uptime?day=7' \
-H 'X-API-Key: YOUR_API_KEY'
Catalog
GET/api/reseller/v1/pools

List available pools

Returns every available pool (Pro only), with all five discounted period prices. Filterable by provider or country.

Query parameters

  • providerstringoptional
    Optional — filter by carrier (e.g. "T-Mobile", "Verizon", "AT&T").
  • countrystringoptional
    Optional — filter by country slug.
RequestCopied!
GET /api/reseller/v1/pools HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"data": [
{
"poolId": "US-1",
"provider": "T-Mobile",
"country": "US",
"state": "california",
"rotation": "30m",
"available": true
}
],
"prices": { "3h":0.32, "12h":0.56, "24h":1.04, "7d":5.6, "30d":20 }
}
GET/api/reseller/v1/pools/{poolId}

Single pool detail

Returns one pool's detail with its own discounted prices.

Path parameters

  • poolIdstringrequired
    Pool ID (e.g. "US-1").
RequestCopied!
GET /api/reseller/v1/pools/US-1 HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"poolId": "US-1",
"provider": "T-Mobile",
"country": "US",
"state": "california",
"rotation": "30m",
"available": true,
"prices": { "3h":0.32, "12h":0.56, "24h":1.04, "7d":5.6, "30d":20 }
}
Errors
  • 401X-API-Key header is missing or invalid.
  • 404Pool does not exist or is unavailable.
GET/api/reseller/v1/prices

Price schedule

Returns the five period prices (post-discount) — quick lookup separate from the pool list.

RequestCopied!
GET /api/reseller/v1/prices HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{ "prices": { "3h":0.32, "12h":0.56, "24h":1.04, "7d":5.6, "30d":20 } }
Errors
  • 401X-API-Key header is missing or invalid.
GET/api/reseller/v1/providers

List providers

Returns the distinct carriers in the catalogue (T-Mobile, Verizon, AT&T, …) with the number of pools per provider. Use this to power a carrier filter in your UI.

RequestCopied!
GET /api/reseller/v1/providers HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"data": [
{ "provider": "AT&T", "poolCount": 1 },
{ "provider": "T-Mobile", "poolCount": 16 },
{ "provider": "Verizon", "poolCount": 20 }
]
}
GET/api/reseller/v1/countries

List countries

Countries available in the catalogue with the number of pools in each. Codes are ISO — the same value you later pass as "country" when provisioning.

RequestCopied!
GET /api/reseller/v1/countries HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"data": [
{ "country": "US", "poolCount": 37 },
{ "country": "GB", "poolCount": 4 },
{ "country": "DE", "poolCount": 2 }
]
}
Errors
  • 401X-API-Key header is missing or invalid.
GET/api/reseller/v1/states

List states

States/regions in the catalogue with pool counts, optionally narrowed to one country via the country parameter. Use it to build a cascading picker: country → state → pool.

Query parameters

  • countrystringoptional
    Restrict to a single country (ISO code, e.g. US).
RequestCopied!
GET /api/reseller/v1/states HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"data": [
{ "country": "US", "state": "Texas", "poolCount": 9 },
{ "country": "US", "state": "New York", "poolCount": 8 }
]
}
Errors
  • 401X-API-Key header is missing or invalid.
Provisioning
GET/api/reseller/v1/units

List your units (paginated)

Returns the proxies your account owns, sorted by poolId. Supports pagination and filters.

Query parameters

  • includeExpiredbooleanoptional
    Optional — true to also include expired units.
  • statusstringoptional
    Optional — exact status filter (ACTIVE / EXPIRED / RELEASED).
  • poolIdstringoptional
    Optional — only units from this pool.
  • expiringWithinHoursintegeroptional
    Optional — only units expiring within N hours.
  • pageintegeroptional
    Optional — page number (default 1).
  • pageSizeintegeroptional
    Optional — page size (default 50, max 200).
RequestCopied!
GET /api/reseller/v1/units HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"data": [
{
"proxyRef": "PRX-12345",
"poolId": "US-1",
"provider": "T-Mobile",
"country": "US",
"state": "california",
"rotation": "30m",
"ip": "203.0.113.45",
"port": 51234,
"protocol": "socks5",
"credentials": { "username": "u_xxx", "password": "p_xxx" },
"status": "ACTIVE",
"createdAt": "2026-05-10T09:00:00.000Z",
"expiresAt": "2026-06-10T09:00:00.000Z",
"expiresIn": 2592000,
"swapCount": 1
}
],
"pagination": {
"page": 1,
"pageSize": 50,
"totalItems": 47,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
Errors
  • 401X-API-Key header is missing or invalid.
GET/api/reseller/v1/units/{proxyRef}

Single unit detail

Returns the details of a specific proxy you own.

Path parameters

  • proxyRefstringrequired
    The proxy reference (e.g. "PRX-9").
RequestCopied!
GET /api/reseller/v1/units/PRX-12345 HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"proxyRef": "PRX-9",
"poolId": "US-1",
"provider": "T-Mobile",
"country": "US",
"state": "california",
"rotation": "30m",
"ip": "108.61.144.196",
"port": 21798,
"protocol": "socks5",
"credentials": { "username": "u_xxx", "password": "p_xxx" },
"status": "ACTIVE",
"createdAt": "2026-05-17T12:16:21.714Z",
"expiresAt": "2026-05-17T15:16:21.714Z",
"expiresIn": 8400,
"swapCount": 0
}
Errors
  • 401X-API-Key header is missing or invalid.
  • 404Unit does not exist or is not owned by you.
GET/api/reseller/v1/units/{proxyRef}/usage

Unit usage

Returns a specific proxy’s consumption with the same numbers the customer app shows. Short plans (POOL: 3h/12h/24h) report plan quota vs used and remaining (mode="pool"). Long plans (weekly/monthly) report today’s usage vs the daily limit (mode="daily"), with the lifetime figure in totalMb.

Path parameters

  • proxyRefstringrequired
    The proxy reference (e.g. "PRX-9").
RequestCopied!
GET /api/reseller/v1/units/PRX-12345/usage HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"proxyRef": "PRX-9",
"mode": "pool",
"scope": "total",
"usedMb": 512,
"usedGb": 0.5,
"quotaMb": 8192,
"quotaGb": 8,
"remainingMb": 7680,
"remainingGb": 7.5,
"percent": 6
}
Errors
  • 401X-API-Key header is missing or invalid.
  • 404Unit does not exist or is not owned by you.
POST/api/reseller/v1/units

Create a new unit

Buys a new proxy from the chosen pool. The discounted price is debited from your balance, and auto-refunded on failure. Send an Idempotency-Key header (a UUID) to guarantee a retry after a network failure never double-charges or double-provisions. The key is honoured for 24 hours: a retry within that window replays the original result, a still-in-flight duplicate gets HTTP 409, and after 24 hours the key is treated as a fresh request.

Request body fields (JSON)

  • poolIdstringrequired
    The pool ID from /pools (e.g. "US-12").
  • periodstringrequired
    Period: ⁨3h⁩, ⁨12h⁩, ⁨24h⁩, ⁨7d⁩, ⁨30d⁩.
  • protocolstringoptional
    Optional — socks5 (default) or http (both use username/password) or inject (HTTP No Auth, IP whitelisted).
  • credentialsobjectoptional
    Optional — { username, password } for custom credentials.
  • allowedIpsstring[]optional
    Required when protocol="inject" — at creation it must contain exactly ONE IP. Additional IPs are added later via PATCH on the unit.
RequestCopied!
POST /api/reseller/v1/units HTTP/1.1
Host: wtproxy.com
Content-Type: application/json
X-API-Key: YOUR_API_KEY
{
"poolId": "US-1",
"period": "30d",
"protocol": "socks5"
}
ResponseCopied!
{
"proxyRef": "PRX-12345",
"poolId": "US-1",
"provider": "T-Mobile",
"country": "US",
"state": "california",
"rotation": "30m",
"ip": "203.0.113.45",
"port": 51234,
"protocol": "socks5",
"credentials": { "username": "u_xxx", "password": "p_xxx" },
"status": "ACTIVE",
"createdAt": "2026-05-17T09:00:00.000Z",
"expiresAt": "2026-06-16T09:00:00.000Z",
"expiresIn": 2592000
}
Errors
  • 400Malformed JSON body.
  • 401X-API-Key header is missing or invalid.
  • 403Reseller mode is disabled for this account.
  • 400Invalid protocol value.
  • 400inject requires at least one allowedIps entry.
  • 402Balance below the required amount.
  • 404The pool does not exist or is unavailable.
  • 503Upstream service unavailable (balance is auto-refunded).
POST/api/reseller/v1/units/{proxyRef}/extend

Extend a unit

Extends a proxy by another period. The discounted price is debited and refunded on failure.

Path parameters

  • proxyRefstringrequired
    The proxy reference (e.g. "PRX-12345").

Request body fields (JSON)

  • periodstringrequired
    Period to add: ⁨3h⁩, ⁨12h⁩, ⁨24h⁩, ⁨7d⁩, ⁨30d⁩.
RequestCopied!
POST /api/reseller/v1/units/PRX-12345/extend HTTP/1.1
Host: wtproxy.com
Content-Type: application/json
X-API-Key: YOUR_API_KEY
{ "period": "7d" }
ResponseCopied!
{
"proxyRef": "PRX-12345",
"expiresAt": "2026-06-23T09:00:00.000Z",
"extended": true
}
POST/api/reseller/v1/units/{proxyRef}/swap

Swap pool

Moves the proxy to another pool while keeping its remaining time. No balance is charged.

Path parameters

  • proxyRefstringrequired
    The proxy reference (e.g. "PRX-12345").

Request body fields (JSON)

  • newPoolIdstringrequired
    The ID of the new pool.
RequestCopied!
POST /api/reseller/v1/units/PRX-12345/swap HTTP/1.1
Host: wtproxy.com
Content-Type: application/json
X-API-Key: YOUR_API_KEY
{ "newPoolId": "EG-3" }
ResponseCopied!
{
"proxyRef": "PRX-12345",
"poolId": "EG-3",
"provider": "Vodafone",
"ip": "198.51.100.7",
"port": 50880,
"protocol": "socks5",
"credentials": { "username": "u_xxx", "password": "p_xxx" },
"expiresAt": "2026-06-23T09:00:00.000Z"
}
POST/api/reseller/v1/units/{proxyRef}/change-protocol

Change protocol (encryption)

Switches the encryption protocol (socks5 ↔ http ↔ http_noauth) while keeping the same proxyRef, remaining time, speed throttle, and consumption history. No balance is charged.

Path parameters

  • proxyRefstringrequired
    The proxy reference (e.g. "PRX-12345").

Request body fields (JSON)

  • newProtocolstringrequired
    The new protocol. One of: "socks5" | "http" | "http_noauth". Must differ from the current value.
  • credentialsobjectoptional
    Optional for socks5/http (reuses existing credentials when omitted). Ignored for http_noauth. Shape: { "username": "...", "password": "..." }.
  • allowedIpsstring[]optional
    Required when newProtocol = "http_noauth" — exactly one client IP to whitelist. Additional IPs can be added later via PATCH /units/{id}.
RequestCopied!
POST /api/reseller/v1/units/PRX-12345/change-protocol HTTP/1.1
Host: wtproxy.com
Content-Type: application/json
X-API-Key: YOUR_API_KEY
{
"newProtocol": "http_noauth",
"allowedIps": ["203.0.113.5"]
}
ResponseCopied!
{
"proxyRef": "PRX-12345",
"poolId": "EG-3",
"provider": "Vodafone",
"ip": "198.51.100.7",
"port": 50880,
"protocol": "http_noauth",
"allowedIps": ["203.0.113.5"],
"expiresAt": "2026-06-23T09:00:00.000Z"
}
Errors
  • 400http_noauth without allowedIps.
  • 404proxyRef not found or not owned by you.
  • 409The newProtocol matches the current value.
PATCH/api/reseller/v1/units/{proxyRef}

Modify a unit

Updates credentials, description, or the allowed-IP list.

Path parameters

  • proxyRefstringrequired
    The proxy reference (e.g. "PRX-12345").

Request body fields (JSON)

  • credentialsobjectoptional
    Optional — new { username, password }.
  • descriptionstringoptional
    Optional — a new description.
  • allowedIpsstring[]optional
    Optional — a new allowed-IP list.
RequestCopied!
PATCH /api/reseller/v1/units/PRX-12345 HTTP/1.1
Host: wtproxy.com
Content-Type: application/json
X-API-Key: YOUR_API_KEY
{
"credentials": { "username": "new_user", "password": "new_pass" }
}
ResponseCopied!
{
"proxyRef": "PRX-12345",
"modified": true
}
DELETE/api/reseller/v1/units/{proxyRef}

Release a unit

Permanently deletes the proxy. No balance is refunded for a manual release.

Path parameters

  • proxyRefstringrequired
    The proxy reference (e.g. "PRX-12345").
RequestCopied!
DELETE /api/reseller/v1/units/PRX-12345 HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"proxyRef": "PRX-12345",
"removed": true
}
Account
GET/api/reseller/v1/me

Account snapshot

Everything you need on session start in one round-trip: balance, discount, unit counts, prices, webhook status.

RequestCopied!
GET /api/reseller/v1/me HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"email": "[email protected]",
"balanceUsd": 142.50,
"discountPercent": 20,
"resellerEnabled": true,
"units": { "active": 12, "total": 47 },
"prices": { "3h":0.32, "12h":0.56, "24h":1.04, "7d":5.6, "30d":20 },
"webhook": { "url": "https://your.app/webhook", "enabled": true }
}
Errors
  • 401X-API-Key header is missing or invalid.
  • 403Reseller mode is disabled for this account.
GET/api/reseller/v1/me/uptime

Account uptime

Uptime across all your units plus a per-unit breakdown. Measured from a probe every 5 minutes per pool — each probe is one "slot", so a full day is 288. Every unit is scored over its OWN lifetime inside the window, so a unit created today is not charged for yesterday. Only up/down readings count; probes that could not reach the provider API are excluded — that is our monitoring failing, not downtime you lived through. Defaults to the last 24 hours, capped at 30 days.

Query parameters

  • dayintegeroptional
    Window length in days (1–30) counted back from now. Default 1. Ignored when from/to are supplied.
  • fromstringoptional
    Window start (ISO-8601). Defaults to ⁨24h⁩ ago.
  • tostringoptional
    Window end (ISO-8601). Clamped to now.
RequestCopied!
GET /api/reseller/v1/me/uptime HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"from": "2026-07-30T21:00:00.000Z",
"to": "2026-07-31T21:00:00.000Z",
"uptimePct": 99.42,
"okSlots": 1700,
"totalSlots": 1710,
"totalUnits": 6,
"probeIntervalMin": 5,
"units": [
{
"proxyRef": "PRX-205981185",
"poolId": "US-TX-3",
"provider": "Verizon",
"country": "US",
"state": "Texas",
"uptimePct": 100,
"okSlots": 288,
"totalSlots": 288
}
]
}
Errors
  • 401X-API-Key header is missing or invalid.
  • 400day out of range, unparseable from/to, or a window longer than 30 days.
  • 429This endpoint’s own budget (10/min) was exceeded. Wait the seconds in Retry-After — the rest of the API stays available.
GET/api/reseller/v1/account

Query balance

Returns the current balance and the discount rate applied to your purchases.

RequestCopied!
GET /api/reseller/v1/account HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"balanceUsd": 142.50,
"discountPercent": 20,
"resellerEnabled": true,
"proxyUsername": "AcmeProxy"
}
PATCH/api/reseller/v1/account

Pin a fixed proxy username

Pins one username to be used on every unit you create afterwards. Without it each proxy gets a random login, so your customers receive different credentials for every unit. Send null to go back to a generated login per unit. Applies to NEW units only — units already provisioned keep their credentials. The password stays per-unit on purpose: pinning it too would mean one leaked pair opens every unit you own. A per-request credentials object still overrides this.

Request body fields (JSON)

  • proxyUsernamestring | nullrequired
    3–32 characters, no spaces, ":" or "@". Send null to clear it.
RequestCopied!
PATCH /api/reseller/v1/account HTTP/1.1
Host: wtproxy.com
Content-Type: application/json
X-API-Key: YOUR_API_KEY
{ "proxyUsername": "AcmeProxy" }
ResponseCopied!
{
"proxyUsername": "AcmeProxy",
"applies_to": "new units only",
"note": "Units already provisioned keep their existing credentials. A per-request "credentials" object still overrides this."
}
Webhooks
GET/api/reseller/v1/webhook

Read current webhook config

Returns the currently configured webhook URL, the HMAC secret, and the enabled flag. If no webhook is set, all fields are null/false.

RequestCopied!
GET /api/reseller/v1/webhook HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"url": "https://your.app/wtproxy-events",
"secret": "whs_abc123…",
"enabled": true
}
Errors
  • 401X-API-Key header is missing or invalid.
PATCH/api/reseller/v1/webhook

Configure webhook

Sets the webhook URL for account events (create / extend / release / low balance). The HMAC secret is returned once — use it to verify the X-WTProxy-Signature header on incoming requests. Pass url=null to disable.

Request body fields (JSON)

  • urlstringoptional
    HTTPS URL to receive events, or null to disable.
RequestCopied!
PATCH /api/reseller/v1/webhook HTTP/1.1
Host: wtproxy.com
Content-Type: application/json
X-API-Key: YOUR_API_KEY
{ "url": "https://your.app/wtproxy-events" }
ResponseCopied!
{
"url": "https://your.app/wtproxy-events",
"secret": "whs_abc123…",
"enabled": true
}
Errors
  • 401X-API-Key header is missing or invalid.
  • 400Invalid URL.
POST/api/reseller/v1/webhook/test

Send a test event

Fires a sample unit.created event at your registered URL through the real delivery pipeline (same signature, same retry policy), with test: true in the payload. Use it to prove your receiver is reachable and your signature check works before the first real event. Watch the outcome via GET /webhook/deliveries.

RequestCopied!
POST /api/reseller/v1/webhook/test HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"sent": true,
"message": "Test event queued. Check GET /webhook/deliveries for the outcome."
}
Errors
  • 401X-API-Key header is missing or invalid.
  • 400No webhook URL is registered — set one first via PATCH /webhook.
GET/api/reseller/v1/webhook/deliveries

Webhook delivery log

Lists recent webhook delivery attempts (success/failure/pending retry) for debugging. Newest first. Supports filtering by status and event.

Query parameters

  • pageintegeroptional
    Page number (default 1).
  • pageSizeintegeroptional
    Items per page (default 25, max 100).
  • statusstringoptional
    Filter by status: PENDING / DELIVERED / FAILED.
  • eventstringoptional
    Filter by event type (e.g., unit.created, unit.released).
RequestCopied!
GET /api/reseller/v1/webhook/deliveries HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{
"data": [
{
"id": "wdl_abc123",
"event": "unit.created",
"url": "https://your.app/wtproxy-events",
"status": "DELIVERED",
"attempts": 1,
"maxAttempts": 5,
"responseStatus": 200,
"lastError": null,
"nextAttemptAt": null,
"createdAt": "2026-05-22T18:30:00Z",
"deliveredAt": "2026-05-22T18:30:01Z"
}
],
"pagination": { "page": 1, "pageSize": 25, "total": 47, "totalPages": 2 }
}
Errors
  • 401X-API-Key header is missing or invalid.
DELETE/api/reseller/v1/webhook

Disable webhook

Removes the webhook URL and secret. No further notifications will be delivered until you set it again via PATCH.

RequestCopied!
DELETE /api/reseller/v1/webhook HTTP/1.1
Host: wtproxy.com
X-API-Key: YOUR_API_KEY
ResponseCopied!
{ "enabled": false }
Errors
  • 401X-API-Key header is missing or invalid.