Skip to content
Coritan Docs

Show your catalogue with the Storefront API

Read your organization's branding, products, locations and currencies without signing in, and take orders from your site.

View as Markdown

The Storefront API gives your site what every visitor sees: your branding, your products and their plans, the locations and software a customer can choose, and your status page. Reading it needs no credential. Placing an order, previewing a coupon and paying an invoice need a signed-in customer's token.

GET /storefront/branding returns what your pages need on every load: org_name, company_name, logo_url, favicon_url, primary_color, secondary_color, support_email, terms_url, privacy_url and default_currency. Colours you have not set come back as #1FA37A and #12141A, and the currency as USD.

It also carries a block for each optional storefront feature, so your site can show only what is switched on:

Block What it tells your site
turnstile Whether to show the Cloudflare Turnstile challenge, and its public site_key.
maintenance Whether to show a maintenance page. Staff signed in to the staff console still see the site.
coupons Whether customers can enter a coupon code.
free_tier Whether free servers can be ordered now, and the ads shown with them.
community_forum, community_knowledgebase Whether the forum and guides are on.
community_chat Whether to show your Discord chat, and the invite link. See Connect a Discord server.
public_server_list Whether the public server list is on, and its categories and tags.
google_analytics, trustpilot Whether to load Google Analytics, and when to ask for a Trustpilot review.
  1. List what you sell:

    Shell
    curl "https://api.coritan.com/api/v1/orgs/acme/storefront/products?category=minecraft"
    

    The answer holds products and org_name. Filter with category (minecraft, games, cloud or addons) or game, and page with page and per_page (up to 200, default 100). A product backed by a server or an instance also says whether it can be ordered right now, in is_orderable_now and stock_status (in_stock or out_of_stock), with the reason in availability_reason.

  2. Open one product by its slug to get its plans:

    Shell
    curl "https://api.coritan.com/api/v1/orgs/acme/storefront/products/survival-smp"
    

    Each plan in pricing has the id you order with, its name, billing_cycle, price, setup_fee and currency. config_schema describes the options the product asks for.

Route What it returns
GET /storefront/locations The data centre locations. Add module=container or module=vps, and optionally hardware_tier_id, to learn which have room: each location then has available, reason and usage_percent.
GET /storefront/vps-templates The operating systems a Cloud Compute order can use, with each one's minimum CPU, memory and disk.
GET /storefront/specializations The games and apps a server can run. product_slug narrows the list to the ones that product features, in its order.
GET /storefront/specializations/{slug}/compose The versions and choices one game or app offers.
GET /storefront/currencies The currencies customers can pay in, with each one's rate against 1 USD.
GET /storefront/timezones The time zones a customer can pick for scheduled tasks.

For Minecraft, GET /storefront/gameproxy/policy says whether an order gets a join address automatically, on which base domain and port. POST /storefront/gameproxy/name-suggestions suggests free names (count up to 20), and POST /storefront/gameproxy/availability?subdomain=... checks one. See Customise the game proxy messages.

For an external server, GET /storefront/external-servers/regions lists the regions it can be served from. POST /storefront/external-servers/probe checks that the customer's own server answers, from upstream_host, upstream_port and mode. It needs the customer's token and is rate limited.

  1. Optionally, check a coupon code for the plan:

    Shell
    curl "https://api.coritan.com/api/v1/orgs/acme/storefront/coupons/preview?code=SPRING&org_product_id=12&org_pricing_id=31" \
      -H "Authorization: Bearer $CUSTOMER_TOKEN"
    

    The answer has valid. When it is true, amount_before and amount_after show the first invoice's total. When it is false, message says why.

  2. Place the order as the customer:

    Shell
    curl -X POST "https://api.coritan.com/api/v1/orgs/acme/storefront/order" \
      -H "Authorization: Bearer $CUSTOMER_TOKEN" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: 3f6c2a9e-order-1" \
      -d '{"org_product_id": 12, "org_pricing_id": 31, "hostname": "survival-smp", "accepted_terms": true, "config": {}}'
    

    | Field | What it holds | | --- | --- | | org_product_id, org_pricing_id | The product and the plan. Both are required. | | hostname | A name for the service, up to 100 characters. | | config | The options the product's config_schema asks for, such as a location. | | accepted_terms | Must be true for a server, an instance or an external server. We record the acceptance with the invoice. | | terms_url | The terms the customer accepted. Defaults to the Terms of service URL in your settings. | | turnstile_token | The Turnstile answer. A free order needs it when turnstile.enabled is true. | | coupon_code | A coupon, taken off the first invoice. A code that does not apply refuses the order. |

    The answer has service_id, invoice_id, invoice_number, total, currency, due_date and requires_payment. status is pending_payment until the invoice is paid, or provisioning when there is nothing to pay. Send the same Idempotency-Key when you retry, and the same order comes back instead of a second one.

  3. Send the customer to pay, as the next section shows. We create the resource once the invoice is paid.

POST /storefront/checkout/{invoice_id} starts a payment for the customer's unpaid or overdue invoice and returns a checkout_url to send them to.

Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/storefront/checkout/5021?currency=EUR" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Origin: https://shop.example.net"

currency defaults to the customer's own, and gateway_name to the gateway we pick for that currency and the customer's country. return_url and cancel_url must be absolute http or https addresses. Leave them out and we build them from the request's Origin: /billing/invoices/{invoice_id}?paid=1 and ?cancelled=1 on your site. The answer also lists the available_gateways for that currency.

Show status, notices and a contact form

Section titled Show status, notices and a contact form
  • GET /storefront/status returns the health of each location, the incidents and maintenance your staff post, and the state of the services your storefront relies on. Resolved incidents stay for 24 hours.
  • GET /storefront/notices returns the notices for visitors who are not signed in. Signed-in customers get theirs from GET /portal/notices, which can target paying customers.
  • POST /storefront/contact sends a visitor's message to your Support email, or to your SMTP from address when there is none, and emails the visitor an acknowledgement. With neither address set, nobody is emailed. It takes name, email and message, with kind set to general or bare_metal_quote and optional company, location, cpu, ram, storage, quantity and timeline. Leave the website field empty: we treat a filled one as a bot. When the visitor sends their customer token, the message also opens a sales conversation in your support inbox.

Your site shows your brand and catalogue to every visitor, and a signed-in customer can order and pay. The order appears on the Services tab and in the customer's invoices, and your webhooks receive order.created.

Product not found or Pricing plan not found
The product is not available, or the plan is turned off or belongs to another product.
Accept the Terms of Service to place this order
Send accepted_terms: true once the customer has ticked your terms.
Order already in progress
The same order with the same Idempotency-Key is still being placed. Wait for the first request to finish.
409 with free_limit_reached, or 503 with free_tier_paused
The customer holds as many free servers as allowed, or free servers are paused for now. Offer a paid plan.
403 Customer account is not active or 403 Service limit reached (500/500)
The customer is suspended or closed, or your organization holds as many services as it may. Ask support to raise the limit.
422 with errors
The options in config cannot be ordered, for example because the location has no room, or the coupon does not apply. The messages say why.
Invoice not found or not payable or No balance remaining
The invoice belongs to another customer, or it is already paid.
return_url and cancel_url are required and must be absolute http(s) URLs ...
Send both, or send an Origin header we can build them from.
429 Too many inquiries. Try again shortly.
One address sent too many contact messages in a short time.

API operations on this page

MethodPathWhat it does
GET/api/v1/orgs/{org_slug}/storefront/brandingPublic branding + legal links for the org storefront
POST/api/v1/orgs/{org_slug}/storefront/checkout/{invoice_id}Create a payment checkout session for a specific invoice
POST/api/v1/orgs/{org_slug}/storefront/contactPublic contact / bare-metal quote intake
GET/api/v1/orgs/{org_slug}/storefront/coupons/previewWhat a code would take off this plan's first invoice, before ordering
GET/api/v1/orgs/{org_slug}/storefront/currenciesPublic enabled pay currencies with FX rates (quote per 1 USD)
POST/api/v1/orgs/{org_slug}/storefront/external-servers/probeCustomer: check a backend before ordering ("Test connection")
GET/api/v1/orgs/{org_slug}/storefront/external-servers/regionsPublic: edge regions an external server can be served from, and the default
POST/api/v1/orgs/{org_slug}/storefront/gameproxy/availabilityStorefront availability
POST/api/v1/orgs/{org_slug}/storefront/gameproxy/name-suggestionsStorefront name suggestions
GET/api/v1/orgs/{org_slug}/storefront/gameproxy/policyPublic: whether Minecraft orders auto-attach gameproxy + base domain
GET/api/v1/orgs/{org_slug}/storefront/locationsPublic DC list, optionally with capacity for a module
GET/api/v1/orgs/{org_slug}/storefront/noticesLive notices for everyone, for the dashboard bar when nobody is signed in
POST/api/v1/orgs/{org_slug}/storefront/orderAuthenticated customer places an order for a product
GET/api/v1/orgs/{org_slug}/storefront/productsPublic endpoint: browse the organization's product catalog
GET/api/v1/orgs/{org_slug}/storefront/products/{product_slug}Public endpoint: view a single product with all pricing tiers
GET/api/v1/orgs/{org_slug}/storefront/specializationsPublic game/app specialization catalog for order UX
GET/api/v1/orgs/{org_slug}/storefront/specializations/{slug}/composeStorefront compose specialization
GET/api/v1/orgs/{org_slug}/storefront/timezonesZones a schedule may be set to, and the old names for them
GET/api/v1/orgs/{org_slug}/storefront/statusPer-location and per-node platform health, for the public status page
GET/api/v1/orgs/{org_slug}/storefront/vps-templatesReady OS templates for Cloud / VPS storefront orders