# 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.

Source: https://www.coritan.com/docs/organizations/storefront/storefront-api/

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.

## Before you begin

- Set up at least one product with an active plan. See [Set up products and pricing](/docs/organizations/products-and-pricing/).
- Fill in your branding on the **Settings** tab. See [Change organization settings](/docs/organizations/settings/).
- To take orders, sign customers in first. See [Sign customers in to your storefront](/docs/organizations/storefront/customer-sign-in/).

## Show your brand

`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](/docs/organizations/storefront/community/) are on. |
| `community_chat` | Whether to show your Discord chat, and the invite link. See [Connect a Discord server](/docs/organizations/integrations/discord/). |
| `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. |

## List products and plans

1. List what you sell:

   ```bash
   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:

   ```bash
   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.

## Offer locations and software

| 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](/docs/organizations/integrations/game-proxy/).

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.

## Take an order

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

   ```bash
   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:

   ```bash
   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.

## Pay an invoice

`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.

```bash
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

- `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](/docs/organizations/staff-console/support-inbox/).

## Result

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](/docs/organizations/webhooks/) receive `order.created`.

## Troubleshooting

`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](https://www.coritan.com/dashboard/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.

## Related

- [Build a storefront on the Organization API](/docs/organizations/storefront/)
- [Build the customer account area](/docs/organizations/storefront/customer-portal/)
- [Manage customer invoices](/docs/organizations/billing/invoices/)

## API

- `GET /api/v1/orgs/{org_slug}/storefront/branding`: Public branding + legal links for the org storefront (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-branding)
- `POST /api/v1/orgs/{org_slug}/storefront/checkout/{invoice_id}`: Create a payment checkout session for a specific invoice (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-post-api-v1-orgs-org-slug-storefront-checkout-invoice-id)
- `POST /api/v1/orgs/{org_slug}/storefront/contact`: Public contact / bare-metal quote intake (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-post-api-v1-orgs-org-slug-storefront-contact)
- `GET /api/v1/orgs/{org_slug}/storefront/coupons/preview`: What a code would take off this plan's first invoice, before ordering (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-coupons-preview)
- `GET /api/v1/orgs/{org_slug}/storefront/currencies`: Public enabled pay currencies with FX rates (quote per 1 USD) (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-currencies)
- `POST /api/v1/orgs/{org_slug}/storefront/external-servers/probe`: Customer: check a backend before ordering ("Test connection") (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-post-api-v1-orgs-org-slug-storefront-external-servers-probe)
- `GET /api/v1/orgs/{org_slug}/storefront/external-servers/regions`: Public: edge regions an external server can be served from, and the default (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-external-servers-regions)
- `POST /api/v1/orgs/{org_slug}/storefront/gameproxy/availability`: Storefront availability (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-post-api-v1-orgs-org-slug-storefront-gameproxy-availability)
- `POST /api/v1/orgs/{org_slug}/storefront/gameproxy/name-suggestions`: Storefront name suggestions (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-post-api-v1-orgs-org-slug-storefront-gameproxy-name-suggestions)
- `GET /api/v1/orgs/{org_slug}/storefront/gameproxy/policy`: Public: whether Minecraft orders auto-attach gameproxy + base domain (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-gameproxy-policy)
- `GET /api/v1/orgs/{org_slug}/storefront/locations`: Public DC list, optionally with capacity for a module (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-locations)
- `GET /api/v1/orgs/{org_slug}/storefront/notices`: Live notices for everyone, for the dashboard bar when nobody is signed in (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-notices)
- `POST /api/v1/orgs/{org_slug}/storefront/order`: Authenticated customer places an order for a product (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-post-api-v1-orgs-org-slug-storefront-order)
- `GET /api/v1/orgs/{org_slug}/storefront/products`: Public endpoint: browse the organization's product catalog (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-products)
- `GET /api/v1/orgs/{org_slug}/storefront/products/{product_slug}`: Public endpoint: view a single product with all pricing tiers (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-products-product-slug)
- `GET /api/v1/orgs/{org_slug}/storefront/specializations`: Public game/app specialization catalog for order UX (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-specializations)
- `GET /api/v1/orgs/{org_slug}/storefront/specializations/{slug}/compose`: Storefront compose specialization (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-specializations-slug-compose)
- `GET /api/v1/orgs/{org_slug}/storefront/timezones`: Zones a schedule may be set to, and the old names for them (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-timezones)
- `GET /api/v1/orgs/{org_slug}/storefront/status`: Per-location and per-node platform health, for the public status page (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-status)
- `GET /api/v1/orgs/{org_slug}/storefront/vps-templates`: Ready OS templates for Cloud / VPS storefront orders (https://www.coritan.com/docs/api/reference/organizations/storefront/storefront/#op-get-api-v1-orgs-org-slug-storefront-vps-templates)
