Client API: Account plan
Your account's plan (Free, Pro, Business or Enterprise), its limits and what the account uses.
Your account's plan (Free, Pro, Business or Enterprise), its limits and what the account uses. Preview, order, change or cancel a plan, start the free trial, and set up the mail, SMTP Relay and Object Storage your plan includes.
Base URL: https://api.coritan.com/api/v1. Paths below are complete.
To try these requests in the browser, open the interactive Client API reference.
Operations
Section titled Operations| Method | Path | Summary |
|---|---|---|
| GET | /api/v1/account/entitlements |
What your plan and add-ons let your account have, and what it uses |
| POST | /api/v1/account/included/{kind} |
Set up the mail, SMTP Relay or Object Storage your plan includes |
| GET | /api/v1/account/plan |
Your plan, the plans you can choose and your free trial |
| POST | /api/v1/account/plan |
Order Pro or Business, or change your plan to it |
| POST | /api/v1/account/plan/cancel |
Cancel your plan |
| POST | /api/v1/account/plan/preview |
What choosing a plan would cost now, and what it would leave over the new plan's limits |
| POST | /api/v1/account/plan/trial |
Start your account's one free trial of Pro or Business |
What your plan and add-ons let your account have, and what it uses
Section titled What your plan and add-ons let your account have, and what it usesGET /api/v1/account/entitlements
What your plan and add-ons let your account have, and what it uses.
The answer is {plan, limits, usage, over_limit, enforced}. plan
is the same object GET /api/v1/account/plan returns. limits holds
every entitlement: a number (-1 for unlimited), true or false for a
feature, or a word for support_level. usage holds the counts we
can measure: websites, load balancers, and the mailboxes, mail domains,
messages sent this month and storage of your included services.
over_limit lists each count above its limit, [{entitlement, limit, used}]: what is over keeps working, and nothing more of it can be
added. enforced is false while plans are not open on your account,
and nothing is refused for a limit until it is true.
Authentication: an access token, sent as Authorization: Bearer <token>.
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
Set up the mail, SMTP Relay or Object Storage your plan includes
Section titled Set up the mail, SMTP Relay or Object Storage your plan includesPOST /api/v1/account/included/{kind}
Set up the mail, SMTP Relay or Object Storage your plan includes.
kind is mail, sending or storage. Each account has one
included service of each kind, at no charge, sized to its plan: on Free,
5 mailboxes of 1 GB on one domain, 3,000 messages a month and 10 GB of
storage. When the plan changes, the service moves with it.
Creating one passes the checks a free order passes: the challenge
(turnstile_token) and a limit on how fast free services are made.
The answer is the service, 201 when this created it and 200 when the
account already had one. Refuses with 404 for another kind, 422 for
a choice the product does not take (storage needs location_id), 403
when the challenge fails, 409 when the account has another free service
of the kind, 429 when free orders come too fast, and 503 when the
service is not available.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
kind |
path | string | yes |
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
turnstile_token |
string or null | no | The Cloudflare Turnstile response, when the page shows one |
domain |
string or null | no | Mail and sending: the first domain. It can be added later. |
region |
string or null | no | Mail and sending: the region code. Left out, the default region. |
location_id |
integer or null | no | Storage: the location the buckets live in. Required. |
bucket_name |
string or null | no | Storage: a first bucket to create |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Fields of a 200 response:
| Field | Type | Description |
|---|---|---|
id |
integer | |
user_id |
integer | |
product_id |
integer | |
pricing_id |
integer | |
hostname |
string or null | |
status |
string | |
billing_cycle |
string | |
amount |
number | |
next_due_date |
string (date-time) or null | |
config |
object or null | |
module_data |
object or null | |
suspension_reason |
string or null | |
provisioned_at |
string (date-time) or null | |
created_at |
string (date-time) | |
updated_at |
string (date-time) | |
product_name |
string or null | |
product_slug |
string or null | |
module_name |
string or null | |
pricing_name |
string or null | |
termination_date |
string (date-time) or null | |
monthly_cap |
number or null | |
hourly_usage_this_month |
number or null | |
hourly_cap_reached |
boolean or null | |
tags |
array of string | |
resource |
ServiceResourceSummary or null | Underlying VPS / Container App / Floating IP summary (DB-backed) |
resource.type |
string | Module resource type: vps | container | ip | external_server |
resource.label |
string or null | Human label: hostname, server name, or IP/CIDR |
resource.status |
string or null | Resource-level status (not billing status) |
resource.address |
string or null | Primary reachability address (IP, IP:port, or CIDR) |
resource.detail |
Detail | Module-specific fields (uuids, node, plan, attach state, …) |
Your plan, the plans you can choose and your free trial
Section titled Your plan, the plans you can choose and your free trialGET /api/v1/account/plan
Your plan, the plans you can choose and your free trial.
plan is {key, name, source, status, renews_at, ends_at, trial_ends_at, service_id, billing_cycle}. key is free,
plan-pro, plan-business or plan-enterprise; source is
paid, trial or free; status is active, cancelling
(it ends at ends_at) or trialing.
available lists Free and each plan on sale: {key, name, prices: {monthly, annually}, popular, orderable, product_id, pricing_ids, limits}. A plan our sales team sells has no prices and is not
orderable. limits holds the plan's own value for every entitlement,
as GET /api/v1/account/entitlements writes them, before add-ons.
trial is {available, plan, ends_at, status}: whether you can
start your one trial now, and the trial you had. enabled is false
while plans are not open on your account; the plan routes that change
something then answer 403.
pending is an order or a plan change waiting for payment, {kind, service_id, plan, name, billing_cycle, invoice_id, amount_due} with
kind order or change; suspended is a plan held for an
unpaid invoice, {service_id, plan, name, invoice_id, amount_due}.
Both are null when there is none.
Authentication: an access token, sent as Authorization: Bearer <token>.
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
Order Pro or Business, or change your plan to it
Section titled Order Pro or Business, or change your plan to itPOST /api/v1/account/plan
Order Pro or Business, or change your plan to it.
Without a plan, this places an order the way POST /api/v1/services/order does: an invoice for the first period, paid
from your credit when it covers it, and the plan starts once it is paid.
promo_code takes a code's discount off that invoice; a code the
order cannot use refuses it with 422, {"errors": [<sentence>], "promo": <reason>}. Ordering again while an order waits for payment
answers with that order, and an order for another plan replaces it.
With an active plan, this changes it the way POST /api/v1/services/{service_ref}/change-plan does: an upgrade invoices
the difference for the rest of the billing period and applies once paid;
a downgrade applies now and credits the unused difference, less the last
few days. Changing the plan withdraws a cancellation, and choosing the
plan you have while it is set to end keeps it renewing.
The answer is {service_id, invoice_id, status, change, amount_due, message}. status is payment_required (pay invoice_id),
provisioning (the plan starts in a moment), changed or
renewing. A running trial ends when the paid plan starts.
Refuses with 403 while plans are not open on your account; with 422 for Free (cancel instead), Enterprise, an unknown plan or billing, and a promo code on a plan change; with 404 for a plan not on sale with that billing; with 409 for the plan you already have, a plan our sales team set, a change of billing period on an active plan, a change while the plan is due to renew, a suspended plan and an order that is being set up.
Authentication: an access token, sent as Authorization: Bearer <token>.
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
plan |
string | yes | plan-pro or plan-business |
billing_cycle |
string or null | no | monthly or annually. Left out, an active plan keeps its own and a new plan is monthly. |
promo_code |
string or null | no | A promo code for a new plan order. A plan change takes none. |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Cancel your plan
Section titled Cancel your planPOST /api/v1/account/plan/cancel
Cancel your plan. The account moves to the Free plan.
A paid plan stays until the end of the period you paid for and then
ends; choosing it again with POST /api/v1/account/plan before then
keeps it. A suspended plan ends now and its unpaid invoice is
cancelled. A trial ends now. A plan order that was never paid is
cancelled with its invoice. Nothing is deleted: what is over the Free
plan's limits keeps working, and nothing more of it can be added.
The answer is {status, ends_at, message}, with status
cancelling (the plan ends at ends_at), ended,
trial_ended or order_cancelled. Refuses with 409 when the plan
is already set to end, when an order is being set up, and when there is
nothing to cancel.
Authentication: an access token, sent as Authorization: Bearer <token>.
Request body
Section titled Request bodyapplication/json
| Field | Type | Required | Description |
|---|---|---|---|
reason |
string or null | no | Why you are leaving, if you want to tell us |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
What choosing a plan would cost now, and what it would leave over the new plan's limits
Section titled What choosing a plan would cost now, and what it would leave over the new plan's limitsPOST /api/v1/account/plan/preview
What choosing a plan would cost now, and what it would leave over the new plan's limits. Nothing changes.
plan is free, plan-pro or plan-business, and
billing_cycle is monthly or annually. promo_code prices a
code on a new plan order as the order would. The answer is {plan, name, billing_cycle, change, due_now, discount, credit, currency, renews_at, renewal_amount, ends_at, over_limit, trial, promo, message}:
changeisnew(an order, paid up front),upgrade(the difference for the rest of this billing period is due now),downgrade(it applies now, and the unused difference goes to your credit less the last few days),cancel(to Free, atends_at),renew(a plan set to end keeps renewing) ornone;over_limitlists each count the new plan would leave above its limit,[{entitlement, limit, used}]. Nothing is deleted: what is over keeps working, and nothing more of it can be added;renew_at_own_pricelists the floating IPs and DDoS Shield profiles the plan pays for now beyond what the new plan pays for,[{entitlement, limit, used}]. The plan keeps paying for the oldest; the newest keep working and renew at their own price from their next renewal;trialisconvertswhen the plan is the same as a running trial's or higher,endswhen it is lower, and null without a trial;discountis what the promo code takes off the first invoice, anddue_nowis what is left.promois{valid, code, message, reason, summary, duration, cycles}, or null without a code.renewal_amountis the plan's price before the code;messagesays all of it in a sentence or two.
Refuses Enterprise and unknown plans or billing (422), a plan that is not
on sale with that billing (404), and with 409: a plan whose terms our
sales team set, a change of billing period on an active plan, a change
while the plan is due to renew, and a suspended plan. A promo code on a
plan change or on Free, or one the order would refuse, answers 422
{"errors": [<sentence>], "promo": <reason>} as POST /api/v1/account/plan does. A refused code counts against the budget
POST /api/v1/billing/promo/validate keeps, and while that budget is
spent a code answers 429 with promo rate_limited.
Authentication: an access token, sent as Authorization: Bearer <token>.
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
plan |
string | yes | free, plan-pro or plan-business |
billing_cycle |
string or null | no | monthly or annually. Left out, an active plan keeps its own and a new plan is monthly. |
promo_code |
string or null | no | A promo code for a new plan order. A plan change takes none. |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Start your account's one free trial of Pro or Business
Section titled Start your account's one free trial of Pro or BusinessPOST /api/v1/account/plan/trial
Start your account's one free trial of Pro or Business.
A trial lasts 14 days, needs no card and creates no invoice. It gives the plan's limits at once and moves your included mail, SMTP Relay and Object Storage up to the plan's allowance. Buying the same plan or a higher one during the trial ends it and keeps what you have; when it runs out, the account returns to Free. We email you 4 days and 1 day before it ends, and when it ends. Nothing is deleted.
The answer (201) is {plan, trial, message}, with plan as GET /api/v1/account/plan returns it. Refuses with 403 while plans are not
open on your account or when the challenge fails, 422 for a plan other
than Pro or Business, 409 when the account has had its trial or has a
paid plan, and 429 after five tries in an hour.
Authentication: an access token, sent as Authorization: Bearer <token>.
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
plan |
string | yes | plan-pro or plan-business |
turnstile_token |
string or null | no | The Cloudflare Turnstile response, when the page shows one |
Responses
Section titled Responses| Status | Meaning |
|---|---|
201 |
Success. |
422 |
The request is not valid. detail lists each problem. |