PARTNER PROGRAM · API V1

Reseller API

Sell dedicated 5G mobile proxies under your own brand. Check live stock, purchase, renew, and rotate credentials programmatically, at your wholesale rate, funded from a prepaid wallet.

BASE URL
https://whitecloakproxy.com/api/reseller/v1

01: ACCESS

Authentication

Every request carries your API key in the Authorization header. Keys are issued to approved partners only. Treat yours like a password: anyone holding it can spend your balance. If it leaks, contact us immediately and we'll rotate it. Requests are limited to 60 per minute.

Support: [email protected] and include your request's idempotency_key or charge_id when reporting a payment issue.

HEADER
Authorization: Bearer wcr_your_api_key_here

02: MONEY

Billing model

Prepaid wallet

You pay us off-platform; we credit your wallet. Every purchase and renewal debits it at your agreed rate for the plan being bought.

Prices in cents

Every amount in every response is US cents: 7350 means $73.50. No floats, no surprises.

Fail-safe charges

If your balance can't cover a request it fails with 402 and nothing is charged or provisioned.

Automatic refunds

If provisioning fails on our side after a charge, the failed units are refunded to your wallet automatically.

Each proxy is a dedicated US mobile device, one device to one customer and never shared, reachable over HTTP and SOCKS5 with a shared password, plus a rotation link your systems can call any time for a fresh IP. Every proxy also takes your own login and password, an automatic rotation interval, an IP whitelist and auto-renew. Sold on five plans: 1 day, 3 days, 1 week, 2 weeks or 1 month, and renewable on any of them.

03: REFERENCE

Endpoints

GET/account

Account

Your wallet balance, your rate for every plan, and how many proxies you currently hold.

REQUEST
curl -H "Authorization: Bearer $KEY" \
  https://whitecloakproxy.com/api/reseller/v1/account
RESPONSE · 200
{
  "success": true,
  "name": "Partner Site",
  "balance_cents": 130000,
  "price_per_proxy_cents": 7350,
  "commission_pct": 25,
  "pricing": [
    { "duration": "daily",    "days": 1,  "price_cents": 600,  "retail_cents": 800 },
    { "duration": "3day",     "days": 3,  "price_cents": 1500, "retail_cents": 2000 },
    { "duration": "weekly",   "days": 7,  "price_cents": 2625, "retail_cents": 3500 },
    { "duration": "biweekly", "days": 14, "price_cents": 4500, "retail_cents": 6000 },
    { "duration": "monthly",  "days": 30, "price_cents": 7350, "retail_cents": 9800 }
  ],
  "pricing_by_carrier": {
    "T-Mobile": [ /* same shape, that carrier's exact rates */ ],
    "Verizon":  [ /* ... */ ]
  },
  "active_proxies": 12,
  "max_active_proxies": null,
  "billing_mode": "wallet"
}
  • ◆Read your prices from here rather than hardcoding them. price_cents is what you pay; retail_cents is our public price it was derived from.
  • ◆commission_pct is the share of retail you keep: every plan is priced as retail x (100 - commission_pct) / 100, so if our retail moves your rate follows and your margin holds. Fixed-rate accounts have commission_pct: null and one price for all plans.
  • ◆pricing is the rate when a purchase names no carrier. Such an order can be filled from any carrier, so it's priced at the highest carrier rate for that plan. Name a carrier to get the exact rate in pricing_by_carrier.
  • ◆price_per_proxy_cents is kept for older integrations and equals the monthly, any-carrier rate.
  • ◆All prices everywhere in this API are US cents: 7350 means $73.50.
  • ◆Watch balance_cents and top up with us before it runs low; purchases fail cleanly with 402 when it can't cover them.
  • ◆billing_mode is either "wallet" (the default, prepaid balance above) or "card" (pay-per-order, see the Purchase endpoint's card billing note). Card accounts always report balance_cents: null here and add a card block: { "last4": "4113", "brand": "VISA" }.
GET/inventory

Inventory

Live purchasable stock, grouped by carrier and US state. Counts refresh continuously.

REQUEST
curl -H "Authorization: Bearer $KEY" \
  https://whitecloakproxy.com/api/reseller/v1/inventory
RESPONSE · 200
{
  "success": true,
  "total_available": 37,
  "stock": [
    { "carrier": "T-Mobile", "state": "FL", "count": 9 },
    { "carrier": "T-Mobile", "state": "NY", "count": 14 },
    { "carrier": "Verizon",  "state": "NY", "count": 8 },
    { "carrier": "Verizon",  "state": "TX", "count": 6 }
  ]
}
  • ◆Stock can sell out between a check and a purchase, and you'd get a clean 409, never a wrong proxy.
POST/purchase

Purchase

Buy 1–20 proxies in one call. carrier and state are guarantees: every delivered proxy matches them, or the call fails before anything is charged.

FIELDTYPE
quantityREQUIREDinteger
durationstring
carrierstring
statestring
idempotency_keystring
REQUEST
curl -X POST \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "quantity": 2,
    "duration": "weekly",
    "carrier": "Verizon",
    "state": "NY",
    "idempotency_key": "your-order-8841"
  }' \
  https://whitecloakproxy.com/api/reseller/v1/purchase
RESPONSE · 200
{
  "success": true,
  "purchased": [
    {
      "proxy_id": "1f6f2a34-....",
      "carrier": "Verizon",
      "state": "NY",
      "host": "relay7.pprx.io",
      "password": "kJ2mPq9xL4",
      "http":   { "port": 10412, "username": "u_8842_http" },
      "socks5": { "port": 10413, "username": "u_8842_s5" },
      "rotation_url": "https://pprx.io/r/AbC123xYz",
      "auto_rotate_minutes": 0,
      "auto_renew": false,
      "expires_at": "2026-08-04T18:20:11.000Z"
    }
  ],
  "failed_count": 0,
  "duration": "weekly",
  "duration_days": 7,
  "unit_price_cents": 2625,
  "charged_cents": 5250,
  "balance_cents": 124750
}
  • ◆Always send an idempotency_key (e.g. your internal order ID). If your request times out and you retry with the same key, you get the original result back instead of being charged twice. A retry while the original is still processing returns 409. Wait and retry again.
  • ◆Use a generous HTTP timeout (120s+): provisioning happens live, one device at a time.
  • ◆Store proxy_id. It's the handle for extend and reset-password.
  • ◆failed_count > 0 means some units couldn't be provisioned and were refunded automatically; purchased contains only real, working proxies.
  • ◆duration sets both how long the proxy lasts and what you're charged. See pricing on the Account endpoint. Omit it and you get a 30-day proxy at the monthly rate.
  • ◆Card billing (opt-in): card payments are processed by Intuit Payments Inc. (QuickBooks Payments). Accounts with billing_mode "card" skip the wallet entirely. We send you a one-time save-card link. Card details are entered and tokenized client-side and never touch our servers, and every purchase after that charges the saved card directly, settling instantly. For these accounts balance_cents is always null and the response adds a payment block that doubles as your per-transaction receipt: { "method": "card", "charge_id": "MT1a2b3c4d", "last4": "4113", "paid_at": "<ISO timestamp>", "processed_by": "Intuit Payments Inc." }.
  • ◆Card billing errors (billing_mode "card" only): 402 { "error": "No card on file. Save a card via your setup link before purchasing." } if you haven't saved a card yet; 402 with a card-specific reason (e.g. "Your card was declined. Please try a different card or contact your bank." or "Your card has expired. Please update your card details.") on a definitive decline; 502 { "error": "Payment status unknown, don't retry; contact support before trying again." } if we couldn't confirm the outcome after a timeout, or a plain 5xx if Intuit's payment_unavailable. In either 5xx case, don't retry blindly; contact support first.
  • ◆Card billing partial failures: if some (not all) units fail to provision after a successful card charge, exactly one partial refund is issued automatically. refund_pending_cents plus a warning only appear if that refund itself failed (rare, our team is alerted), the same convention as the wallet path's refund_pending_cents.
GET/proxies

List proxies

Every active (unexpired) proxy you hold, soonest-expiring first. Same unit shape as the purchase response.

REQUEST
curl -H "Authorization: Bearer $KEY" \
  https://whitecloakproxy.com/api/reseller/v1/proxies
RESPONSE · 200
{
  "success": true,
  "count": 12,
  "proxies": [ { "proxy_id": "...", "expires_at": "...", ... } ]
}
  • ◆Poll this daily and renew anything expiring within a day or two, or turn on auto-renew per proxy and let us do it. Expired proxies are released back to the pool and can't be recovered.
  • ◆auto_renew and auto_rotate_minutes show each proxy's current settings, so you can read them back after changing them.
POST/proxies/extend

Extend

Renew one proxy on the plan of your choice. Extending early never loses time: the new period stacks onto the current expiry.

FIELDTYPE
proxy_idREQUIREDstring
durationstring
REQUEST
curl -X POST \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"proxy_id": "1f6f2a34-....", "duration": "weekly"}' \
  https://whitecloakproxy.com/api/reseller/v1/proxies/extend
RESPONSE · 200
{
  "success": true,
  "proxy_id": "1f6f2a34-....",
  "expires_at": "2026-08-11T18:20:11.000Z",
  "duration": "weekly",
  "duration_days": 7,
  "unit_price_cents": 2625,
  "charged_cents": 2625,
  "balance_cents": 122125
}
  • ◆Omit duration and the proxy renews on the same plan your customer already has, so a weekly proxy renews for another week at the weekly rate. Pass one explicitly to move a customer between plans.
  • ◆Send one extend per proxy at a time: if two race, the second is detected, refunded, and answered with 409. Treat that as "already extended" and re-check GET /proxies.
  • ◆A 410 means the proxy already expired and was released, and it can't be brought back.
POST/proxies/reset-password

Reset password

Generate a fresh password for one proxy. HTTP and SOCKS5 both switch within about a second. Use it when handing a proxy to a different end customer.

FIELDTYPE
proxy_idREQUIREDstring
REQUEST
curl -X POST \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"proxy_id": "1f6f2a34-...."}' \
  https://whitecloakproxy.com/api/reseller/v1/proxies/reset-password
RESPONSE · 200
{
  "success": true,
  "proxy_id": "1f6f2a34-....",
  "password": "nEw9pAsS2q"
}
POST/proxies/credentials

Custom login and password

Set your own username and/or password on a proxy instead of the generated ones. Live on HTTP and SOCKS5 within about a second.

FIELDTYPE
proxy_idREQUIREDstring
passwordstring
http_usernamestring
socks5_usernamestring
REQUEST
curl -X POST \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "proxy_id": "1f6f2a34-....",
    "http_username": "acme_ny_01",
    "socks5_username": "acme_ny_01s",
    "password": "s3cret-pass"
  }' \
  https://whitecloakproxy.com/api/reseller/v1/proxies/credentials
RESPONSE · 200
{
  "success": true,
  "proxy_id": "1f6f2a34-....",
  "http":   { "username": "acme_ny_01",  "password": "s3cret-pass" },
  "socks5": { "username": "acme_ny_01s", "password": "s3cret-pass" }
}
  • ◆Send any one field or several. Anything you leave out keeps its current value.
  • ◆Letters, numbers and - _ . ~ only. Anything else breaks user:pass@host URLs and host:port:user:pass lists, so it's refused up front.
  • ◆Usernames are unique across our whole network, so the HTTP and SOCKS5 ports each need their own, and a name someone else already has returns 409. Prefix them with your brand to avoid collisions.
  • ◆If one port accepts the change and the other refuses it, the error response still lists the credentials that are live on each port right now.
  • ◆POST /proxies/reset-password still works afterwards and puts a fresh generated password on both ports.
POST/proxies/auto-rotate

Auto-rotation interval

Rotate a proxy's IP automatically on a timer, from every 2 minutes to once a day.

FIELDTYPE
proxy_idREQUIREDstring
minutesREQUIREDinteger
REQUEST
curl -X POST \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"proxy_id": "1f6f2a34-....", "minutes": 10}' \
  https://whitecloakproxy.com/api/reseller/v1/proxies/auto-rotate
RESPONSE · 200
{
  "success": true,
  "proxy_id": "1f6f2a34-....",
  "auto_rotate_minutes": 10
}
  • ◆The rotation_url keeps working with auto-rotation on, so your customer can still force a new IP between scheduled ones.
  • ◆Each rotation drops open connections for a few seconds while the phone reconnects to the carrier.
POST/proxies/auto-renew

Auto-renew

Have a proxy renewed automatically before it expires, on its current plan at your rate, paid from your wallet.

FIELDTYPE
proxy_idREQUIREDstring
enabledREQUIREDboolean
REQUEST
curl -X POST \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"proxy_id": "1f6f2a34-....", "enabled": true}' \
  https://whitecloakproxy.com/api/reseller/v1/proxies/auto-renew
RESPONSE · 200
{
  "success": true,
  "proxy_id": "1f6f2a34-....",
  "auto_renew": true,
  "expires_at": "2026-08-11T18:20:11.000Z",
  "renews_within_hours_of_expiry": 3
}
  • ◆We check every hour and renew anything with auto-renew on that expires in the next 3 hours. Renewing early never loses time, the new period stacks onto the current expiry, same as calling extend yourself.
  • ◆It renews on the plan the proxy is on now, so a weekly proxy renews for another week at your weekly rate. To move a customer to another plan, call extend with that duration once and auto-renew follows from then on.
  • ◆If your balance can't cover a renewal, we retry on every hourly run until the proxy expires. Top up in that window and it still renews. After expiry it's released like any other lapsed proxy.
  • ◆Auto-renew charges your wallet, so watch balance_cents on GET /account the same way you would for manual renewals.
GET/proxies/whitelist

IP whitelist: read

The IP addresses allowed to use a proxy without a username or password.

FIELDTYPE
proxy_idREQUIREDstring
REQUEST
curl -H "Authorization: Bearer $KEY" \
  "https://whitecloakproxy.com/api/reseller/v1/proxies/whitelist?proxy_id=1f6f2a34-...."
RESPONSE · 200
{
  "success": true,
  "proxy_id": "1f6f2a34-....",
  "ips": ["203.0.113.7", "198.51.100.0/24"],
  "enabled": true,
  "max_entries": 20
}
PUT/proxies/whitelist

IP whitelist: set

IP authorization. Requests from the listed addresses use the proxy's HTTP and SOCKS5 ports with no login. Everyone else still needs the username and password.

FIELDTYPE
proxy_idREQUIREDstring
ipsREQUIREDstring[]
REQUEST
curl -X PUT \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"proxy_id": "1f6f2a34-....", "ips": ["203.0.113.7", "198.51.100.0/24"]}' \
  https://whitecloakproxy.com/api/reseller/v1/proxies/whitelist
RESPONSE · 200
{
  "success": true,
  "proxy_id": "1f6f2a34-....",
  "ips": ["203.0.113.7", "198.51.100.0/24"],
  "enabled": true
}
  • ◆This replaces the whole list. To add one address, read the list, append, and send it back.
  • ◆Ranges can't be broader than /16 for IPv4 or /32 for IPv6, since anyone inside a wider range could use the proxy with no password. Loopback, multicast and 0.0.0.0 are refused for the same reason.
  • ◆Blank entries and duplicates are dropped, and the response shows the list as it was saved.

04: FAILURE

Errors

Errors always return { "error": "human-readable message" }.

400Invalid request body or parameters
401Missing or invalid API key
402Wallet accounts: insufficient balance (required_cents included). Card accounts: no card on file, or the card was declined/expired.
403Key deactivated, or purchase would exceed your proxy cap
404proxy_id not found (or not yours)
409Not enough matching stock, duplicate in-flight request, raced extend, or a custom username that's already taken
410Proxy already expired and was released
429Rate limit exceeded (60 requests/minute)
500Something failed on our side; any charge was refunded (or a refund is pending, see refund_pending_cents)
502Card accounts only: payment outcome couldn't be confirmed after a timeout, don't retry; contact support

05: SHIP IT

Recommended integration

  1. 1

    Show stock

    Pull GET /inventory and present purchasable carriers and states to your customers.

  2. 2

    Sell & deliver

    Customer pays on your site → POST /purchase with their chosen carrier/state → hand them the host, ports, username, password, and rotation URL.

  3. 3

    Renew daily

    Turn on auto-renew per proxy, or run a daily job that lists GET /proxies and extends anything expiring soon. A proxy your customer didn't pay for just lapses.

  4. 4

    Stay funded

    Watch GET /account and top up with us before your balance runs low.

BECOME A PARTNER

Need an API key?

Reseller access is invite-only. Tell us about your volume and your audience and we'll set you up with a wholesale rate and a prepaid wallet.

Contact us