Skip to content
Coritan Docs

Connect your game network to your storefront

Send your game servers' status, market, leaderboards and players to Coritan, and deliver what your customers buy in game.

View as Markdown

If you run a game network, such as a group of Minecraft servers, the program that runs it can send Coritan what happens in game, and your storefront can show it: whether the network is up, how many play, the market's prices and the leaderboards. The same program reads what your customers buy and tells Coritan when each purchase reached the player, so the customer can see it on their order.

Your program sends and reads with an organization API key. Your website reads the reports without one.

  • Create an organization API key with the network:write scope on the API keys page, as Create organization API keys describes. It can send every report, record deliveries and read purchases. A key with network:read can only read purchases. Send the key in the X-API-Key header.
  • Sell what the network delivers as Standalone products, which Set up products and pricing covers. Your program only sees purchases of standalone products.
  • Coritan keeps your network's public settings: the addresses players join on, your Discord invite, your vote sites and the characters your network puts before some players' names. Ask support to set or change them. What your website reads lists them.

PUT /api/v1/orgs/{org_slug}/network/status replaces the status. Send it every 15 to 60 seconds:

Shell
curl -X PUT https://api.coritan.com/api/v1/orgs/acme/network/status \
  -H "X-API-Key: $ORG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"online": true, "players_online": 412, "max_players": 2000, "version_label": "1.21.x", "season": {"name": "Season 1", "started_at": "2026-10-17T14:00:00Z"}, "regions": [{"key": "eu", "name": "Europe", "players_online": 250}, {"key": "na", "name": "North America", "players_online": 162}]}'
Field Required What it holds
online Yes true while players can join.
players_online Yes Players online across the network, from 0 to 10,000,000.
max_players No How many players the network takes at once, or null.
version_label No The game versions players can join with, as your site shows them, such as 1.21.x. Up to 40 characters.
season No The season running now, with its name (up to 80 characters) and when it started_at, or null between seasons.
regions No Players online in each region, up to 20, each with a key of your own, a name (up to 60 characters) and players_online. Leave it out for a network with one region.

The answer is {"kind": "status", "updated_at": "2026-10-17T14:00:05Z"}, with the time Coritan saved the push. Times without an offset are read as UTC, and every time Coritan sends back is in UTC.

PUT /api/v1/orgs/{org_slug}/network/market replaces the market with the items you send, so an item you leave out leaves the market. Send it every one to five minutes:

Shell
curl -X PUT https://api.coritan.com/api/v1/orgs/acme/network/market \
  -H "X-API-Key: $ORG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"currency_symbol": "$", "items": [{"key": "diamond", "name": "Diamond", "category": "Ores", "sell": 92.5, "buy": 101, "change_24h": -2.5, "volume_24h": 1840}]}'

Each item has a key of your own and a name (up to 80 characters). It can also have:

  • category, the group your site files it under, up to 40 characters.
  • sell, what a player gets for selling one, and buy, what a player pays for one.
  • change_24h, how far the price moved over the last 24 hours, in percent: -2.5 for down 2.5%.
  • volume_24h, how many changed hands over the last 24 hours.

Send null, or leave the field out, for what does not apply, such as buy for an item players cannot buy. A push holds up to 1,000 items, each key once. currency_symbol is what your site shows with prices, $ when you leave it out. The answer is {"kind": "market", "updated_at": ...}.

PUT /api/v1/orgs/{org_slug}/network/leaderboards replaces every board. Send them every five to fifteen minutes:

Shell
curl -X PUT https://api.coritan.com/api/v1/orgs/acme/network/leaderboards \
  -H "X-API-Key: $ORG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"boards": [{"key": "richest", "title": "Richest players", "unit": "money", "entries": [{"rank": 1, "name": "Alex", "uuid": "5b0c0d4e-7f1a-4c2b-9d3e-1a2b3c4d5e6f", "value": 1250000}]}]}'

A board has a key of your own, a title (up to 60 characters), a unit and up to 100 entries. The unit says what each entry's value counts: money, count, duration in seconds, or time in milliseconds, for a best time such as a parkour run. Each entry has its rank from 1, a name (up to 40 characters), its value, and the player's uuid, or null for an entry that is not one player, such as a team.

A push holds up to 30 boards, each key once, in the order your site shows them. Coritan stores each board's entries in rank order. The answer is {"kind": "leaderboards", "updated_at": ...}.

POST /api/v1/orgs/{org_slug}/network/players records the players your network has seen, so your site can look a name up, for example to check the name a customer types when they buy something for a player. Send the players seen since your last request every 30 to 60 seconds, up to 1,000 a request:

Shell
curl -X POST https://api.coritan.com/api/v1/orgs/acme/network/players \
  -H "X-API-Key: $ORG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"players": [{"uuid": "5b0c0d4e7f1a4c2b9d3e1a2b3c4d5e6f", "name": "Alex", "edition": "java", "last_seen": "2026-10-17T14:02:11Z"}]}'
  • uuid is the player's UUID, with or without dashes.
  • name is the name the game shows, with the character your network puts before it, if any, such as .Alex: an optional - or ., then 1–16 letters, digits and underscores.
  • edition is java, java_offline for a non-premium Java Edition account, or bedrock.
  • last_seen is when the player was last on the network. A time in the future counts as now.

Coritan keeps one record for each uuid, with the name and edition of the latest sighting, so a player who changes their name is found by the new one. A sighting older than the one kept changes nothing. The answer is {"saved": 1}, the number of different players in the request.

These routes need no key and no sign-in. Their paths start with /api/v1/orgs/{org_slug}, as on the rest of this page:

Route What it returns
GET /network/status The status as you last sent it, with the addresses players join on: online, players_online, max_players, version_label, java_address, bedrock_address, bedrock_port, season and regions.
GET /network/market The items as you last sent them, the categories they use in the order they first appear, and currency_symbol.
GET /network/leaderboards The boards as you last sent them.
GET /network/players/lookup?name=Alex Whether a player with that name, in any case, has been seen.

The status, the market and the leaderboards also carry updated_at, the time of your last push of that report, and stale. stale is true when the last push is more than five minutes old, so your site can say the figures may be out of date, for example while your network is down. Before your first push, a report has no figures yet: updated_at is null, stale is true, the lists are empty and the status's numbers are null. The status's addresses come from your network's settings, so they are there before the first push.

The lookup answers {"found": true, "player": {"name": "Alex", "uuid": "5b0c0d4e-7f1a-4c2b-9d3e-1a2b3c4d5e6f", "edition": "java", "last_seen": "2026-10-17T14:02:11Z"}} for the player seen most recently with that name, or {"found": false}. Its name takes the same form as a player's name above, and anything else answers 422.

A push can take up to a minute to reach every visitor. Coritan keeps each answer for up to 15 seconds, and the Cache-Control header lets browsers and caches each keep it for 15 seconds and serve it for 15 more while they fetch a new one. An organization slug that does not exist, or whose organization is not active, answers 404 Organization not found.

GET /api/v1/orgs/{org_slug}/storefront/branding carries your network's public settings in network. Until Coritan sets them, the answer has no network.

Field What it holds
enabled Whether your site shows the network.
java_address, bedrock_address, bedrock_port The addresses players join on, for each edition.
discord_url Your Discord invite.
vote_sites Up to 20 sites where players vote for your network, each with a name and a url.
hosting_org The slug of another organization whose server hosting your site offers, or null.
hosting_panel_url Where that organization's customers manage their servers.
name_rules offline_prefix and bedrock_prefix: the character your network puts before the name of a non-premium Java Edition player and of a Bedrock Edition player, or null for none.

A link that is not an https:// address comes back as null.

GET /api/v1/orgs/{org_slug}/network/entitlements lists your organization's services of standalone products in the order they last changed: by updated_at, then by service_id. It needs a key with network:read or network:write.

Shell
curl "https://api.coritan.com/api/v1/orgs/acme/network/entitlements?updated_after=2026-10-17T14:00:00Z&limit=100" \
  -H "X-API-Key: $ORG_API_KEY"
JSON
{
  "entitlements": [
    {
      "service_id": 5012,
      "customer_id": 881,
      "product_id": 12,
      "product_slug": "gold-rank",
      "status": "active",
      "billing_cycle": "monthly",
      "config": {"minecraft_name": "Alex", "minecraft_edition": "java"},
      "next_due_date": "2026-11-17T14:03:00Z",
      "termination_date": null,
      "created_at": "2026-10-17T14:01:40Z",
      "updated_at": "2026-10-17T14:03:00Z",
      "delivery": null
    }
  ],
  "next_cursor": null
}
  • status is where the purchase stands, such as pending until it is paid, active, suspended or terminated. Give the player what the purchase grants while it is active, and take it away when the purchase is suspended or terminated.
  • config holds the details the customer gave when ordering, such as the player to deliver to, and the delivery you last recorded.
  • next_due_date is when the next payment is due. termination_date is when a cancelled purchase ends, or null.
  • delivery is the delivery you last recorded, or null before the first.

updated_after keeps the purchases that changed at or after a time, in ISO 8601. limit is how many come in a page: 100 unless you ask for 1–500. While next_cursor is not null, pass it back as cursor for the next page.

Any change to a purchase, such as a payment, a renewal, a cancellation or a delivery you record, gives it a new updated_at, so it comes again at the end of the list. To keep up, ask again every 15 to 60 seconds with updated_after set to a minute before the latest updated_at you have handled. A change can be saved a moment after the time it carries, and the minute's overlap catches it. You will see some purchases twice, so skip one whose updated_at you have already handled.

Tell Coritan how a delivery went with POST /api/v1/orgs/{org_slug}/network/entitlements/{service_id}/delivery:

Shell
curl -X POST https://api.coritan.com/api/v1/orgs/acme/network/entitlements/5012/delivery \
  -H "X-API-Key: $ORG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "delivered", "detail": "Your rank is active on every server."}'
  • status is delivered once the player has it, waiting while it waits for them (until they next join, for example) or failed when it could not be given.
  • detail is an optional sentence of up to 300 characters. The customer's account returns it with the purchase (GET /api/v1/orgs/{org_slug}/portal/services/{service_id}), so your storefront can show it: write it for the customer.

Coritan saves it in the purchase's config.delivery as {"status": "delivered", "at": "2026-10-17T14:03:00Z", "detail": "Your rank is active on every server."}, in place of the delivery recorded before. The answer is {"entitlement": {...}}, the purchase as the list shows it. Each delivery is in your organization's audit log as service.delivery_recorded, under the API key, with its status and detail.

Your website's reads return what your program sent, and stale turns true if it stops sending. Each purchase carries how its delivery went in config.delivery, and the audit log holds an entry for each delivery you record.

What Limit
Size of one push 2 MB
Regions in the status 20
Items in the market 1,000
Boards 30, each with up to 100 entries
Players in one request 1,000
A price, a volume or a score 1,000,000,000,000,000 either way
A delivery's detail 300 characters
Purchases in a page 500
Requests with one key The key's rate limit: 4,000 an hour unless you chose another

The intervals on this page add up to fewer than 1,000 requests an hour, and one more for each delivery you record. The website's reads need no key, so they do not count.

403 with scope_required
The key lacks the scope the route needs, and the message names it, such as This API key needs the network:write scope. You cannot add a scope to a key, so create a new key with it.
404 Organization not found
The organization slug in the path is not the key's organization, or, on a read without a key, no active organization has that slug.
404 with not_found
The service_id is not a purchase of one of your organization's standalone products.
413 with payload_too_large
The push is larger than 2 MB. Send fewer items or players in each request.
422 with a detail list
A field is wrong. Each entry names it in loc, such as ["body", "items", 0, "sell"], with the reason in msg: two items with one key, a number that is NaN or Infinity, an edition that is not one of the three, a limit outside 1–500. Coritan saved nothing from the request.
422 with invalid and "field": "cursor"
The cursor is not one the list gave out. Pass the next_cursor of the page before, or leave it out and start again from updated_after.
stale stays true
No push of that report has arrived in the last five minutes. Check that your program is running and that its pushes answer 200.

A missing, wrong or revoked key, an address outside the key's allow-list and a key past its rate limit answer as Create organization API keys describes.

API operations on this page

MethodPathWhat it does
PUT/api/v1/orgs/{org_slug}/network/statusReplaces the network's status
PUT/api/v1/orgs/{org_slug}/network/marketReplaces the market
PUT/api/v1/orgs/{org_slug}/network/leaderboardsReplaces the leaderboards: up to 30 boards of up to 100 entries each
POST/api/v1/orgs/{org_slug}/network/playersRecords players the network has seen, so the website can look a name up
GET/api/v1/orgs/{org_slug}/network/statusThe network's status as the backend last pushed it, with the addresses players join on
GET/api/v1/orgs/{org_slug}/network/marketThe market as the backend last pushed it
GET/api/v1/orgs/{org_slug}/network/leaderboardsThe leaderboards as the backend last pushed them, each board's entries in rank order
GET/api/v1/orgs/{org_slug}/network/players/lookupWhether the network has seen a player with this name
GET/api/v1/orgs/{org_slug}/network/entitlementsLists the purchases the network delivers, in the order they last changed
POST/api/v1/orgs/{org_slug}/network/entitlements/{service_id}/deliveryRecords how a purchase's delivery went