Solutions and prices API
Read the solutions on offer and their prices, and install one.
A bundle is the set of apps one kind of organisation, its archetype, is
offered as a single item, from the files in catalog/bundles. It is offered
once a platform admin gives it a price on the Prices page, until it is
withdrawn.
Every price here is the team's own: a lower price while the bundle has one for the team, and the Standard price otherwise. A team's price is fixed with its first solution, installed or paid for, from the address that did it (the X-Real-Ip header Traefik writes), and its every month is charged at it. Until then a price is the one for the address asking.
A bundle or an install's terms priced below Standard also give list_price_cents,
the Standard price, and give none otherwise.
List Bundles
GET /api/v1/teams/{teamSlug}/bundlesResponse 200: {"bundles": [...]}, each bundle with its id, name,
archetype, its apps (each with its id, name, what it does, who it is
sized_for, whether it backs_up its data, and alone_cents, what it would
cost a month on its own), its monthly price_cents for the team
(null until it has one), whether it is offered, alone_cents, what its apps would cost a month bought
one by one, and saving_cents, what its price saves against that (null when it
saves nothing). Every member of the team may read it.
Bundles on Offer
GET /api/v1/bundlesNo session needed: the public pages read it for each visit.
Response 200: {"bundles": [...]}, only the bundles on offer, each with
its id, name, archetype, its apps (each with its id, name, what it
does, who it is sized_for, and whether it backs_up its data) and its
monthly price_cents for the visitor, as /prices gives it. A bundle
with no price, or one withdrawn, is left out.
Prices
GET /api/v1/pricesNo session needed: the public pages read it for each visit.
Response 200: {"rates": {...}, "addons": [...], "solutions": [...]}.
rates are what App hosting charges, gb_hour_cents, vcpu_hour_cents and
volume_gb_month_cents (null when the plans differ). addons are those on
sale, each with its id, kind, name, days and monthly price_cents.
solutions are the bundles on offer, each with its id, name, use_case,
apps (id and name) and monthly price_cents for the visitor:
a lower price for the addresses staff have set one for, and the Standard price for any other address, an unknown one, or with no
country database. A solution priced below Standard also carries list_price_cents,
the Standard price, and one at Standard carries none. The price comes from the request's address, looked up in
the country database the API image carries; nothing is kept, and the answer
does not say how the price was chosen.
Terms of an Install
GET /api/v1/teams/{teamSlug}/bundles/{bundleId}/termsThe terms an install of the bundle by the caller would take, for the confirm
to show and then send to the install: the bundle's monthly price_cents for
the team, whether the install starts the free trial, trial_ends_at, when that
trial would end were the install made now, or null when the install takes
its first month from the team's credit instead, and has_paid, whether a
payment has reached the team. The install starts the trial when it is the
team's first bundle and neither the caller nor the team has had one, and
records the end the confirm showed. When the trial ends, a team that has paid
is charged the bundle's first month. One that has not is charged nothing, its
apps stop 72 hours later, and the first month starts with its first payment.
Response 200:
{"bundle_id": "hospital", "price_cents": 12200, "trial": true, "trial_ends_at": "2026-11-14T10:00:00Z", "has_paid": false}It runs the install's checks without making anything, and answers a check
that fails as the install would: 403 unless the caller is one of the team's
owners or admins, 404, 409 bundle_not_offered, 409 bundle_installed,
402 billing_required, and 402 insufficient_credit when the install starts
no trial and the team's credit is below the bundle's monthly price.
Install a Bundle
POST /api/v1/teams/{teamSlug}/bundles/{bundleId}/installMakes one app for each app in the bundle, as a catalog install does, and
records them as one install. Its body is the terms the installer's confirm
showed: the bundle's monthly price, whether the install starts the free
trial, when that trial ends, null without one, and whether it showed the team
as having paid.
{"price_cents": 12200, "trial": true, "trial_ends_at": "2026-11-14T10:00:00Z", "has_paid": false}Clusterz answers each app's setup itself, with the app's address, the installer's email, the team's name and an administrator's password of the app's own.
A team's first bundle starts the 14-day free trial, which needs no credit: each person has one trial, by their verified email and their account, and so does each team. Any other bundle takes its first month's price from the team's credit as it installs. Every check runs before anything is made:
403unless the caller is one of the team's owners or admins;400without the confirm'sprice_centsandtrial, or without itstrial_ends_atwhen it showed a trial;404for a bundle the platform does not ship;409 bundle_not_offeredfor a bundle with no price, or withdrawn;409 bundle_installedwhen the team holds the bundle already, an install of it with an app left, as a second click finds it; nothing was made or charged;402 billing_requiredwhen the team's balance is below zero or its apps are paused;402 insufficient_creditwhen the install starts no trial and the team's credit is below the bundle's monthly price;409 price_changedwhen the price or the trial differs from the confirm's, the confirm'strial_ends_atlies more than an hour from 336 hours after the install, as a confirm left open for over an hour shows, or a trial'shas_paiddiffers from the confirm's, with the terms as they now stand, as the terms route gives them; nothing was made or charged;409when another install took the trial meanwhile; nothing was made;- an app that cannot be installed answers as a catalog install does, with
the app's id in
app.
Response 201: the install (id, team_id, bundle_id, created_by,
created_at, and trial_ends_at: when the free trial it started ends, the
end its confirm showed, as recorded and as billing keeps to, or null when it
paid its first month) and its apps, each with its catalog_id, its
project and its state: setting_up once its first release has started,
or needs_attention with an error when it could not be set up or started.
Such an app has a failed deployment, which the deployment's retry runs
again; the bundle's other apps carry on.
An app whose settings could not be stored keeps none of them. Its retry
(POST .../deployments/{deployId}/retry) first answers its setup again, as
the install did: its address, the installer's email, the team's name as it is
now and a new administrator's password, which How to sign in on its page then shows.
An app that kept its settings keeps them, since its databases were made with
the passwords in them.