Upstream Connections
Resell another FluxBilling platform's catalogue from your own store: connect with the supplier's reseller key, sync and price their products, and let every order provision automatically.
What an upstream connection is
An upstream connection lets your platform resell another FluxBilling platform's catalogue as if it were your own. The other platform is the supplier: it approves you as a reseller, sells to you at wholesale, and builds and runs the services. Your platform pulls the supplier's catalogue, publishes the products in your own store at your own price, and when one of your customers pays, places the wholesale order at the supplier automatically. The customer sees a service on your platform, under your brand, with the IP address the supplier delivered. Nothing is ordered, activated, suspended or cancelled by hand.
It is one of two ways to buy from another FluxBilling platform, and the right one for a white-labelled storefront:
| Arrangement | Who orders | Where the service lives for your customer |
|---|---|---|
| Upstream connection (this article) | Your platform, automatically, the moment a customer pays you | On your platform, as a normal service in your store, with the supplier's controls forwarded |
| Panel link (Panel Links) | You, by hand, from the Reseller area of your client panel | On the supplier's platform; your portal browses and manages it through their API |
Note: the Upstream Connections card needs the Resellers feature enabled for your company (Settings → Feature Toggles → Resellers). Your own reseller programme does not have to be switched on: buying wholesale and selling wholesale are separate decisions. If you sell through the Reseller API yourself, this is the other side of the same contract.
How money and services flow
- Your customer buys the product in your store and pays you through your own payment gateways, at your retail price. The supplier never sees that payment.
- Your platform places a wholesale order at the supplier using the API key they issued you. The supplier charges your reseller account there in the way they have chosen for their programme: a saved card, your prepaid credit balance with them, or an invoice you pay first.
- The supplier builds the service and tells your platform when it is active. The local service switches from Pending to Active, with the server IP and hostname filled in, and your customer is notified as for any other service.
- From then on the service is yours at the supplier, billed to your account on its cycle. Power, console, reinstall, password reset and backups on your customer's service page are forwarded to the supplier where their product supports them. Suspend, unsuspend, terminate and package changes are forwarded too.
Note: you pay the supplier for every service you hold there until you terminate it. Suspending your customer's service does not stop the supplier's billing to you — terminating it does.
Before you start
Everything below comes from the supplier's platform, from your reseller profile there (their client panel → Reseller → API Settings). Your profile must be approved (active) first.
| Item | Details |
|---|---|
| An API key | Create it with the scopes read, orders, services and destructive, plus account so your platform can register its webhook address on the supplier by itself. Without account you paste that address into the supplier's API Settings by hand (see The webhook address below). Copy the key when it is shown; it is not shown again. |
| The signing secret | Shown in full on the same page (Reveal). It signs every order and lifecycle call your platform makes and verifies the supplier's status webhooks. It is required — a connection cannot be created without it, because without it the connection would pass its test and then have every order refused. |
| The supplier's address | The root address of their platform, for example https://panel.supplier.example. Not the link to their API documentation and not a path into the API: your platform adds the API path itself. A pasted documentation link or trailing slash is stripped on save. |
Step 1: add the connection
Open Settings → Reseller Program and scroll to the Upstream Connections card at the bottom. The toggle in the card header controls automatic product sync only — the connection list is always shown, and ordering, lifecycle forwarding and webhook processing run whenever a connection exists. Click Add Connection.
| Field | What to enter |
|---|---|
| Connection Name * | A label for your own use, for example the supplier's company name. |
| Description | Optional notes. |
| Platform API URL * | The supplier's root address (see above). |
| Reseller API Key * | The key the supplier issued you. When editing later, leave it blank to keep the stored one. |
| Signing Secret * | The signing secret from the supplier's API Settings page, 16 characters or more. When editing, leave it blank to keep the stored one. |
| Sync Interval (hours) | How often the catalogue is refreshed automatically when auto-sync is on (1–168, default 24). |
| Default Markup (%) | Added on top of the supplier's wholesale price when your local products are created and repriced. You can change it later; the new value applies at the next sync. |
| Auto-sync products automatically | Keeps the catalogue and wholesale prices refreshing on the interval above. |
- Fill in the fields and click Test Connection. Success reports how many products the supplier offers you; a failure shows the reason (wrong address, a revoked key, or a reseller profile that is not active).
- Click Create Connection. Your platform immediately tries to register its webhook address on the supplier and tells you whether that worked. If it did not, the message says why — most often the key is missing the account scope.
Tip: always test before saving. A connection saved with a wrong key sits in an Error state, and every order placed on its products fails.
Step 2: the webhook address
The supplier tells your platform that a service was provisioned, suspended, unsuspended or terminated by delivering webhooks to an address that is unique to each connection. Every connection row shows that address under the supplier's URL, with a Copy webhook address link.
- Registered automatically when the key carries the account scope: nothing else to do.
- Otherwise, paste the address into your reseller profile on the supplier's platform (their client panel → Reseller → API Settings → Webhook URL), or add the account scope to the key and click the Register webhook on supplier action on the connection row.
Note: without the webhook address on file at the supplier, a paid order still goes through — but the local service stays Pending until your platform's hourly check polls the supplier and activates it. Set the address before the first order.
Step 3: sync the catalogue
Click Sync Products on the connection row. Your platform reads every product the supplier has marked available to resellers, with the wholesale price you get per billing cycle, and stores them as synced products. The Products column counts them. The same click also reprices the local products you already created (see Pricing after creation) and reports what changed.
A product the supplier stops offering disappears from their catalogue; the sync notices, marks it withdrawn, takes the matching local product off sale, and a notification in the admin bell names it — so nobody can buy what the supplier will refuse. If the product comes back it is re-enabled in the synced list only; the local product stays off sale until you re-enable it under Products. An empty catalogue answer withdraws nothing, because that is far more often a wrong key than a supplier with nothing to sell.
Wholesale prices are restated into your platform's base currency first, using your exchange rates, so a markup is never applied to a foreign amount. A product whose currency your platform cannot convert is stored but not priced until a rate exists.
With Auto-sync products automatically on and the card's toggle enabled, the same sync runs on the interval you set. A sync that fails (the supplier unreachable, a revoked key) puts the connection in Error with the reason shown under its status; the next successful sync sets it back to Active.
Step 4: create your local products
Click Auto-create Local Products. A dialog asks for the category the new products should go into, then creates one product in your catalogue for every synced product that has none yet:
- the supplier's product name and description;
- a retail price per billing cycle of wholesale × (1 + markup), including the setup fee;
- active in your store, and not offered to your own resellers.
Important: pick a general category. Your store lists products through their category, so a product with none is on sale but invisible to customers. Do not use a VPS, dedicated-server or colocation category: those switch the order form to your own infrastructure (local plans, operating systems, hardware), which a resold product does not have.
The supplier's add-ons come along: for every add-on the supplier offers on a product, a matching add-on is created on yours (also at wholesale plus your markup), so what your store sells is what the supplier can deliver. Add-ons the supplier withdraws are withdrawn from your product on the next sync; add-ons that are not the supplier's cannot be attached to a resold product — the editor refuses them, because nobody could deliver them.
Afterwards open each product in Products as you would any other and finish it off: name, description, feature bullets, image and visibility. The product list shows Resold from <supplier> in the Provisioning column and the editor banner names the supplier, so resold products are easy to tell apart, and the product stays wired to the supplier whatever category you move it to.
Pricing after creation
Every sync — the automatic one and the Sync Products button — reprices your linked products from the supplier's current wholesale price and your markup, so a supplier price change reaches your store within the sync interval, or immediately when you click. If you set a price by hand instead, switch off Keep prices in sync with the supplier in the product's Upstream banner; the sync then leaves that product's prices (and its add-ons' prices) alone. Turn it back on to return to automatic pricing.
The margin guard
Every time the supplier charges you for an order, your platform records the charge with its currency, restates it into your own currency at your rate, and compares it with what the customer paid you for the same first cycle (price, setup fee and add-ons). You get a billing notification when the charge is at or above what the customer paid (a negative margin), when the margin is below the floor you set (Alert when the margin on a resold order is below (%), default 5, on the Reseller Program page), when the charge is more than 2% above what the last sync said it should be (an exchange-rate move or a supplier price change — click Sync Products), or when the supplier bills in a currency you have no rate for. Nothing is blocked: the customer has already paid, so the guard tells you rather than stops you.
What happens on an order
| What the supplier answers | What you see |
|---|---|
| Paid, being built | The local service is Pending until the supplier's provisioned webhook arrives (or the hourly check finds it active); then Active with IP and hostname, and the customer's order completes. |
| Invoice raised (the supplier collects by invoice) | Nothing is built until you pay that document at the supplier; the local service waits as Pending, and a billing notification in the admin bell tells you which document to pay. |
| Payment refused (card declined, credit balance short) | The local service becomes Provisioning failed with the reason, and a billing notification appears in the admin bell. Fix the payment side at the supplier, then retry the service from its automation log: the retry asks the supplier to retry that order — it never places a second one, and it is not retried automatically. |
| Charged but not built | Same as above, with a note not to re-order: contact the supplier quoting the order. A retry from your side is refused for this case. |
Your customer's hostname, when it is a valid server name, is passed to the supplier; the operating system is the supplier's default for that plan.
Lifecycle and reconciliation
- Suspend / unsuspend / terminate / package change on a resold service are forwarded to the supplier. If the supplier does not accept one, the local change stands, and a billing notification tells you the supplier's state has diverged so you can sort it out with them.
- Supplier-side changes arrive as webhooks and are mirrored on the local service, with the bookkeeping a local change would carry. A suspension records when and why (usually your unpaid invoice with them) and raises a billing notification; a termination closes the local service, cancels its open invoices so the customer is not dunned for a server that no longer exists, and raises a notification; an unsuspension restores the service.
- Hourly check: orders that have waited more than an hour for a webhook are polled at the supplier and activated if they are ready; terminations the supplier could not process are retried, because you keep paying until they go through. This runs whether or not the card's toggle is on.
- Non-payment: when your customer stops paying, the service is suspended after your usual grace and then terminated at the supplier after Terminate a resold service this many days after suspension (Reseller Program page, default 3 days) — deliberately shorter than the general termination grace, because the supplier keeps billing you for every day in between. Suspending a resold service raises a notification with the termination date, so you can terminate at once when no payment is expected.
Managing the connection
| Item | Meaning |
|---|---|
| Active | Syncing and ordering normally. |
| Error | The last sync or test failed; the message is shown under the status. Ordering and the hourly check keep running; the next successful sync clears it. |
| Paused / Disabled | Paused is the row's Pause / Resume action: no syncing and no ordering until you resume, nothing lost. Disabled is set when editing the connection and is the permanent form of the same thing, keeping the history. |
| Edit Connection | Change the name, address, interval or markup; leave the key and secret blank to keep them. |
| Register webhook on supplier | Re-sends your webhook address to the supplier (needs the account scope on the key). |
| Delete Connection | Only possible while the connection has never placed an order; it also withdraws the products it created from sale. A connection with order history cannot be deleted — set it to Disabled instead, so the record of what you bought stays. |
Each row also carries three small chips — Connection, Products and Webhook — and a one-line next step (sync first, then create local products), so the order of the actions is visible without this article.
The Share VPS clusters action on a connection row belongs to native VPS cluster sharing between two platforms and is described with the VPS documentation.
What your customer sees
A resold service is not a stub with a power button. Your customer opens it in your client panel and gets the same service page the supplier's own customers get for that kind of service: a dedicated server with its hardware, location, network interfaces, storage, subnets and addresses, reverse DNS, traffic graph, hardware health, SSH keys, rescue mode and OS reinstall; a VPS with its addresses, operating system, snapshots and console; an IP transit service with its port, BGP session and self-service BGP settings; a colocation service with its device and cross-connects; a game server with the whole game panel (files, backups, schedules, mods, SFTP, console); a provider-built service with the page its provider ships. The supplier is never named on any of it.
How it works: on each visit your platform reads the supplier's service document for the service (what their panel renders, with their per-product switches), keeps it for twenty seconds, and remembers the kind and the switches on the service so a supplier outage shows the last known shape instead of an empty page. The per-kind pages answer from the supplier ahead of your own modules, so you do not need the inventory, IP transit, colocation or game modules to resell those services. Consoles open a session on the supplier and your panel's viewer connects there. SSH keys stay stored on your platform; attaching one hands the public key to the supplier under your reseller account.
Add-ons after the sale. When your customer buys an add-on on a running resold service, or cancels one, your platform hands the supplier the add-ons the service must now carry. The supplier charges your reseller account the wholesale difference — a new add-on at its first cycle plus setup fee, a quantity increase at the unit price, a removal for free — in your payment mode there, and delivers it to the server the way its own sales are delivered. The charge is recorded on the service and a billing notification (“Supplier charged an add-on change”) names the amount. If the supplier cannot charge you, the notification says so and names the supplier order to settle; an add-on the supplier does not offer is flagged on the service as needing an operator instead of being sold silently. Only add-ons that came from the supplier's catalogue can be attached to a resold product in the first place.
Limits to know
- A supplier product that prices by datacentre needs a location chosen at order time, which your store does not collect for resold products; such products cannot be sold this way yet.
- Your customers cannot choose an operating system; the supplier's plan default is installed. Reinstalls from the service page do offer the supplier's templates.
- The supplier bills you for renewals on each service's cycle but sends no renewal webhook; watch Billing in your client panel on the supplier's platform.
- Your customers exist at the supplier only as reference records with no login there.
- A supplier product with no monthly price (sold only per hour or per year) cannot be created as a local product; Auto-create reports it.
- The margin guard checks each order's charge. The supplier's renewal charges for a running service are not re-checked, so a large exchange-rate move shows up on the next order, not on the renewal.
Troubleshooting
| Symptom | Look at |
|---|---|
| Test Connection fails | The address must be the supplier's root; the key must be unrevoked and unexpired; your reseller profile there must be active (a pending or suspended profile answers Invalid API key). |
| “Webhook could not be auto-registered” | The reason is in the message. Add the account scope to the key and use Register webhook on supplier, or paste the address at the supplier by hand. |
| Products synced but not in the store | They have no category, or their category is not public. Open the product and set one. |
| A product went off sale by itself | The supplier withdrew it; the notification names it. When the supplier lists it again you get another notification, and you re-enable the local product yourself. |
| Prices you set keep reverting | Switch off Keep prices in sync with the supplier on that product. |
| Service stays Pending after payment | The webhook address is not set at the supplier, or their delivery failed. Ask the supplier to check the delivery log for your profile; the hourly check activates the service on its own once the supplier reports it active. |
| “Upstream supplier rejected an order” notification | Your payment at the supplier failed (card, credit balance) or their invoice for the order is unpaid. Settle it there, then retry the service. |
| “Negative margin” / “Thin margin” / “charged more than the synced wholesale” | The supplier's charge for one order against what the customer paid, or against the last sync. Raise the local price, run Sync Products, or check the exchange rate under Settings → Billing → Currencies. |
| “Resold order carries an add-on the supplier cannot deliver” | The order includes an add-on that is not one of the supplier's. Nothing was ordered at the supplier. Refund or remove the add-on, and keep only the supplier's add-ons on resold products. |
| “Upstream … failed — supplier state has diverged” | A suspend, unsuspend or terminate did not reach the supplier. Terminations are retried hourly; for the rest, repeat the action or contact the supplier. |
Related
Reseller Program · Reseller API · Panel Links · The Reseller Area · Webhooks · Products
