Proxy./ docs

Reseller API: act as your customers

For approved resellers: name each of your customers with X-Reseller-Customer-Id and every call runs as them: isolated plans and balances per customer, orders at your negotiated rates, and a customer book with contact identity.

The reselling guide's loop runs everything through YOUR account and tags plans with labels. Approved resellers get a stronger model: your key names one of your customers per request, and the call runs as that customer: their own plans, their own spendable balance, their own order history, fully isolated from every other customer. You price in your business dashboard, we charge you your negotiated rates, and your customers never see us anywhere.

Reseller access is granted, not self-served. Apply from Reseller in your dashboard with the account whose key you already use; we review every application in person and reply on the account's email. Approval provisions your rate card and opens your business dashboard (balance, statement, customers, your prices, storefront, support inbox). Your reseller API key, carrying the act_as_reseller_customer scope, is one you create in that dashboard under Storefront, API access; it is shown once, and you can hold up to three and revoke any of them there. The reselling guide walks the four steps.

Naming a customer

Add one header to any /api/v1 call. The id is yours (your user id, an email hash, anything stable): up to 64 characters of letters, digits, _, -, .. It is scoped to your account, so two businesses using the same id refer to different people and can never see each other's data. The customer is created the first time you name one, so there is no signup call.

Any call, as your customer
curl https://hproxy.com/api/v1/plans \
  -H "X-API-Key: hpx_your_key_here" \
  -H "X-Reseller-Customer-Id: user-4021"

Without the header, the same key acts as your own account (your wallet, your deposits), which is how you top up your reseller balance. With it, reads and writes belong to that customer.

How the money works

Your customers pay you, on your site, with your payment methods. You mirror what they paid you as store credit on that customer (from your business dashboard, or from your own backend with PUT /customer/credit), and their orders spend that credit at your prices while your prepaid reseller balance is charged your negotiated rate in the same transaction. The gap is your margin, and it never appears in anything their side can read. When their credit is short an order fails with 402 customer_credit_insufficient; when your balance is short, 402 reseller_balance_insufficient. Nothing half-charges. Your storefront can also take the payment itself: connect your own gateway (Heleket or NOWPayments for crypto, Stripe or Payoneer Checkout for cards) under Payments in your business dashboard, and POST /deposits for a named customer returns a pay page on your merchant account. What arrives is credited to that customer automatically, underpayments and overpayments included. Without a gateway for the requested method the call answers 403 deposits_not_available; there is never a payment page of ours for your customers to reach.

GEThproxy.com/api/v1/customerkey
curl https://hproxy.com/api/v1/customer \
  -H "X-API-Key: hpx_your_key_here" \
  -H "X-Reseller-Customer-Id: user-4021"

Read the acting customer

The named customer's profile: your id for them, your display name (label), the email you attached, the credit they can still spend (in cents, at your prices), and when they were created and last seen. Requires the X-Reseller-Customer-Id header.

PUThproxy.com/api/v1/customer/contactkey
curl -X PUT https://hproxy.com/api/v1/customer/contact \
  -H "X-API-Key: hpx_your_key_here" \
  -H "X-Reseller-Customer-Id: user-4021" \
  -H "Content-Type: application/json" \
  -d '{"email": "alex@example.com", "label": "Alex M."}'

Attach their identity

Set the customer's email and your display name for them, ideally right after your own signup flow, so your customer book, your business dashboard and our support all see a person instead of an opaque id. Each field: omitted = unchanged, empty string = cleared, value = set. We never send mail to this address; it is identity, not a channel.

ParameterTypeRequiredDescription
emailstringoptionalThe customer's email address. Stored lowercased. Empty string clears it.
labelstringoptionalYour display name for them, 1 to 120 characters. Empty string clears it.
PUThproxy.com/api/v1/customer/creditkey
curl -X PUT https://hproxy.com/api/v1/customer/credit \
  -H "X-API-Key: hpx_your_key_here" \
  -H "X-Reseller-Customer-Id: user-4021" \
  -H "Content-Type: application/json" \
  -d '{"amount_cents": 2500, "direction": "grant", "request_id": "pay_8f3a21", "note": "Stripe pi_3Q…"}'

Credit or revoke their balance

Move store credit on the named customer, from your own backend: grant when they paid you, revoke for a refund on your side or a correction. Amounts are whole cents at your retail prices; one movement is at most $5,000. Send your own request_id for every movement (your payment id, your refund id): a repeat with the same id answers 409 already_applied instead of moving the credit twice, so a retry is always safe. A revoke larger than what is left is refused (revoke_exceeds_credit) and names the remaining figure. Requires the X-Reseller-Customer-Id header.

ParameterTypeRequiredDescription
amount_centsintegerrequiredPositive whole cents at your prices.
directionstringrequired"grant" or "revoke".
request_idstringrequiredYour id for this movement, one per intent, 1 to 100 characters.
notestringoptionalShown on your statement, up to 200 characters.
POSThproxy.com/api/v1/depositskey
curl -X POST https://hproxy.com/api/v1/deposits \
  -H "X-API-Key: hpx_your_key_here" \
  -H "X-Reseller-Customer-Id: user-4021" \
  -H "Idempotency-Key: topup_8f3a21" \
  -H "Content-Type: application/json" \
  -d '{"amount_cents": 2500, "method": "crypto", "return_url": "https://shop.example.com/wallet"}'

Let the named customer pay you

With X-Reseller-Customer-Id, this creates an invoice on your own payment gateway (connected under Payments in your business dashboard) and returns its pay page: crypto through Heleket or NOWPayments (method: "crypto"), cards through Stripe Checkout or Payoneer Checkout (method: "card"); one live gateway per rail. The page shows your merchant name, the money goes to your account, and when it arrives we credit the customer's store credit automatically: the exact amount, the whole amount when they overpay, and what actually arrived when a crypto invoice closes short. Amounts are whole cents; sub-floor amounts are raised to the method floor ($3 crypto, $10 card) and one invoice is at most $5,000. Send an Idempotency-Key and a retried request returns the same open invoice. No gateway for that method ⇒ 403 deposits_not_available.

An order can pay for itself. POST /orders for a named customer with method: "crypto" or "card" and short credit still answers 402 customer_credit_insufficient, but with payUrl, depositId, chargeCents (the shortfall raised to the rail's minimum) and shortfallCents added. Send the customer to payUrl: when the money lands, the credit is granted and the order is placed automatically under the same Idempotency-Key, a Telegram customer is told in the store's bot, and GET /deposits/{id} shows for_order: true. Without a gateway for that rail the 402 carries no pay page and the customer needs credit first.

ParameterTypeRequiredDescription
amount_centsintegerrequiredWhole cents at your prices.
methodstringoptional"crypto" or "card". Default "card".
return_urlstringoptionalWhere the customer lands after paying (https). Default: your website, else your Telegram storefront.
GEThproxy.com/api/v1/deposits/{id}key
curl https://hproxy.com/api/v1/deposits/rpay_cmt9x2k1a0001 \
  -H "X-API-Key: hpx_your_key_here"

Read one of your customers' payments

The state of a deposit your storefront created, for your own backend to show "payment received". status is awaiting_payment, paid, paid_over, underpaid, expired, cancelled, failed, locked (held by the gateway; nothing credited) or needs_review. credited_cents is what landed on the customer's store credit. Account-level: no customer header needed, and only your own deposits resolve.

ParameterTypeDescription
GEThproxy.com/api/v1/usagekey
curl "https://hproxy.com/api/v1/usage?days=7" \
  -H "X-API-Key: hpx_your_key_here" \
  -H "X-Reseller-Customer-Id: user-4021"

A customer's bandwidth history

With X-Reseller-Customer-Id, the named customer's traffic from the meter: one row per day and one per plan over the last days days (1 to 365, default 30). gbUsed is what was consumed that day; null means no reading exists for that day (a plan's first day, or a gap) and is never zero, and unknownDays counts those. Each day also carries gbTotal (the caps of the plans measured that day) and gbLeft (what they still held at the day's last reading), so how much a customer had and how much is left is a history, not a snapshot. Each plan line carries its cap, the meter at the last reading (gbUsedEnd) and gbLeft. Narrow to one plan with plan_id. What they bought is on GET /orders; this is what they used. Readings land every 30 minutes, one pass after the plan's own figures are synced, so a plan bought in the last hour may have no row yet; for a live figure read the plan itself (GET /plans/{id}).

ParameterTypeRequiredDescription
daysinteger (query)optionalWindow in days, 1 to 365. Default 30.
plan_idstring (query)optionalOne plan only.
GEThproxy.com/api/v1/store/usagekey
curl "https://hproxy.com/api/v1/store/usage?days=30" \
  -H "X-API-Key: hpx_your_key_here"

Your whole store's bandwidth

Account-level (no customer header): what all your customers used per day beside what you sold per day, per product, and the ten customers that used the most, over the last days days. gb_used is the meter, gb_sold is GB on paid orders by the day they were paid, gb_total and gb_left are what the measured plans had and still held at the day's last reading; the four are never mixed into one number. unknown_days counts plan-days without a reading. Readings land every 30 minutes, one pass after each plan's own figures are synced. Snake_case like the other account-level doors.

ParameterTypeRequiredDescription
daysinteger (query)optionalWindow in days, 1 to 365. Default 30.
GEThproxy.com/api/v1/customerskey
curl "https://hproxy.com/api/v1/customers?limit=50" \
  -H "X-API-Key: hpx_your_key_here"

List your customers

Every customer on your account, newest first, with identity and credit, the read your backend reconciles against. This is an account-level call: send it without the X-Reseller-Customer-Id header (naming a customer here is refused with a 400 telling you to drop the header).

ParameterTypeRequiredDescription
limitinteger (query)optionalPage size, 1 to 200. Default 50.
offsetinteger (query)optionalRows to skip. Default 0.

The whole loop, as one customer

Signup to delivery
# 0. Your customer signs up on YOUR site -> create + identify them
curl -X PUT https://hproxy.com/api/v1/customer/contact \
  -H "X-API-Key: hpx_your_key_here" -H "X-Reseller-Customer-Id: user-4021" \
  -H "Content-Type: application/json" \
  -d '{"email": "alex@example.com", "label": "Alex M."}'

# 1. They paid you -> mirror it as credit, from your backend (or in the
#    business dashboard: Customers -> user-4021 -> Add credit)
curl -X PUT https://hproxy.com/api/v1/customer/credit \
  -H "X-API-Key: hpx_your_key_here" -H "X-Reseller-Customer-Id: user-4021" \
  -H "Content-Type: application/json" \
  -d '{"amount_cents": 2500, "direction": "grant", "request_id": "pay_8f3a21"}'
# Their balance, any time:
curl https://hproxy.com/api/v1/wallet \
  -H "X-API-Key: hpx_your_key_here" -H "X-Reseller-Customer-Id: user-4021"
# -> { "balanceCents": 2500, "currency": "USD" }  (their credit, your prices)

# 2. They buy on your site -> order AS them (Idempotency-Key is REQUIRED here)
curl -X POST https://hproxy.com/api/v1/orders \
  -H "X-API-Key: hpx_your_key_here" -H "X-Reseller-Customer-Id: user-4021" \
  -H "Idempotency-Key: your-order-83741" \
  -H "Content-Type: application/json" \
  -d '{"product_id": "residential-lite", "quantity": 5}'

# 3. Deliver: generate lines from THEIR plan (free, repeatable)
curl https://hproxy.com/api/v1/plans \
  -H "X-API-Key: hpx_your_key_here" -H "X-Reseller-Customer-Id: user-4021"
curl -X POST https://hproxy.com/api/v1/plans/{planId}/generate \
  -H "X-API-Key: hpx_your_key_here" -H "X-Reseller-Customer-Id: user-4021" \
  -H "Content-Type: application/json" \
  -d '{"count": 100, "country": "US", "stickyMinutes": 10}'

Dedicated IPs work the same way: list the countries in stock with GET /products/{id}/options (always current, sold-out countries drop out on their own), quote and order with country and period_days in fulfillment_meta while naming the customer, then GET /proxies?order_id=… as that customer once the order completes. Renewals too: the ids must belong to the acting customer, exactly as ownership works everywhere else.

Rules the lane enforces

An Idempotency-Key is required on every reseller order (a plain key merely should send one; a reseller key must, and an order without one is refused before any charge): only your system knows whether a request is a new sale or a retry, and this is what makes retries free. Isolation is structural: a customer id that is not yours simply does not resolve, plan and proxy ownership follow the acting customer, and GET /plans for customer A can never show customer B's plans. Reseller keys also carry a higher rate-limit tier, sized for a whole storefront (thousands of customers behind one key) rather than a single integration, so a busy shop or a bulk operation is never throttled for being busy.

Your catalog
On a reseller key, GET /products is your rate card: the products we have priced for you and nothing else, which can include storefront-only products the public catalog does not list. Everything about them (pricing, options, ordering) works exactly like every other product on this page, and every quote on this key is at your prices. The other direction is yours too: a product you hide in your business dashboard (Pricing, then Hide) leaves your catalog and your bot on their next read, and an order for it as one of your customers answers 409 product_unavailable.

Lock your key to your servers

Your reseller key is a server-to-server credential, so you can pin it to the IP addresses your own backend calls us from. Set the allowlist in your business dashboard under Storefront → Key access, and the key stops working from anywhere else. A leaked copy is inert. It is off by default, holds a handful of IPv4/IPv6 addresses, and restricts only the API key: the dashboard is a separate, session-authed login, so a wrong entry locks your integration, never you out of fixing it. A call from a disallowed IP is refused with 403 ip_not_allowed.

Where the rest lives
Issue and revoke customer credit, set your prices, watch your statement and answer your customers' support messages in your business dashboard. The API is the selling lane; the dashboard is the business lane.

Need a hand wiring this up? Email support@hproxy.com. A real person reads every message.