# Supercraft Agentic API - Guide for AI Agents

> It is the first thing an AI agent should read when helping a user with [supercraft.host](https://supercraft.host) game server hosting.

---

## What is Supercraft?

[supercraft.host](https://supercraft.host) is a game server hosting platform. Users rent dedicated game servers for multiplayer games like Valheim, Minecraft, Palworld, ARK, and 25+ other games. Servers run on distributed nodes across 4 global regions.

**Base API URL:** `https://claws.supercraft.host`
**OpenAPI spec:** `https://claws.supercraft.host/openapi.json`

---

## What you can do for the user

As an AI agent, you can help users with the entire server lifecycle:

1. **Recommend a plan** - browse games, compare plans, suggest the best fit
2. **Purchase** - generate a checkout link so the user can pay
3. **Set up the server** - pick region, install game, configure settings
4. **Manage the server** - start, stop, restart, change config, send console commands
5. **Troubleshoot** - check status, read logs, verify connection details

---

## Quick Reference: Key Endpoints

| What you want to do | Endpoint | Auth needed? |
|---------------------|----------|-------------|
| List available games | `GET /catalog/games` | No |
| Get plans & pricing for a game | `GET /catalog/games/{game_code}` | No |
| List server regions | `GET /catalog/regions` | No |
| Start a purchase (new user) | `POST /orders/purchase` | No |
| Get login link (existing user) | `POST /auth/login-link` | No |
| Claim credentials (poll after purchase or login) | `GET /auth/claim?magic={token}` | No |
| Request password reset for user | `POST /auth/reset-password` | No |
| List user's servers | `GET /servers` | Bearer token |
| Server status | `GET /servers/{id}` | Bearer token |
| Install game | `POST /servers/{id}/install` | Bearer token |
| Start server | `POST /servers/{id}/start` | Bearer token |
| Stop server | `POST /servers/{id}/stop` | Bearer token |
| Restart server | `POST /servers/{id}/restart` | Bearer token |
| Get connection details | `GET /servers/{id}/connection` | Bearer token |
| Read config | `GET /servers/{id}/config` | Bearer token |
| Update config | `PUT /servers/{id}/config` | Bearer token |
| Config schema (what options exist) | `GET /servers/{id}/config/schema` | Bearer token |
| Send console command | `POST /servers/{id}/console` | Bearer token |
| Read server logs | `GET /servers/{id}/logs` | Bearer token |
| Available games for plan | `GET /servers/{id}/available-games` | Bearer token |
| Switch to different game | `POST /servers/{id}/switch-game` | Bearer token |

All authenticated endpoints require: `Authorization: Bearer {jwt_token}`

Trusted agent integrations should also send: `X-Agent-Key: sk_agent_...`
If no agent key is sent, the request is tracked as `unknown`.

---

## Workflow 1: New user wants a game server

This is the most common scenario. The user has no account and wants to get a server running.

### Step 1: Understand what the user needs

Ask about:
- **Which game?** If unsure, show them the game list.
- **How many players?** This determines the plan.
- **Mod support needed?** Some plans don't include mods.
- **Budget preference?** Longer subscriptions save money.

```
GET /catalog/games
GET /catalog/games/{game_code}
```

### Step 2: Recommend a plan

Use the plan data to make a recommendation. Plans are keyed as "S", "M", "L". Each plan has a `description`, `features` (dict of feature name → value), and `prices` (dict with "1 month", "3 months", "6 months", "12 months", each containing `amount` and `product_id`). Example logic:
- 1-5 players, no mods → Plan S (smallest)
- 6-10 players or mods needed → Plan M (mid)
- 10+ players or heavy mods → Plan L (largest)
- Suggest 3-month billing for savings if user seems committed

Tell the user the price and what they get. Be specific about features.

### Step 3: Generate checkout link

```
POST /orders/purchase
Body: { "product_id": <selected_product_id> }

Response: {
  "magic": "a8f3k9x2m5p7...",
  "checkout_url": "https://supercraft.host/?add-to-cart=14&magic=a8f3k9x2m5p7...",
  "claim_endpoint": "/auth/claim?magic=a8f3k9x2m5p7...",
  "product_name": "Valheim Plan S - 1 month",
  "price": "28.99",
  "currency": "USD",
  "expires_in_seconds": 3600
}
```

Tell the user:
> Please open this link to complete your purchase. It's a secure Stripe checkout - you'll create an account and enter payment details.

**Important:** Give the user the full `checkout_url`. Don't modify it. The `magic` parameter is how you'll get API access after they pay.

### Step 4: Claim credentials

⚠️ **STOP — You must send the checkout link to the user NOW, before doing anything else.**

Do not call any tools, do not start polling, do not run any commands. Your very next action must be a message to the user containing the `checkout_url`. If you call a tool (like `exec`, `curl`, or a cron setup) before sending the message, the user will never receive the link on most platforms.

**This is the #1 mistake agents make.** You get the checkout URL and immediately start polling — but the message with the link never reaches the user because tool calls block message delivery.

Correct sequence:
1. **Reply to the user** with the `checkout_url` — this must be your response, not a tool call
2. **After the user's next message** (or in a cron job), start polling `/auth/claim`

**Setting up polling (do this AFTER sending the link):**

The best approach is a cron job. Set one up to run every 30 seconds:
```bash
# Cron command (run every 30s):
curl -sL "https://claws.supercraft.host/auth/claim?magic=TOKEN_HERE"
```

If your platform doesn't support cron, poll `/auth/claim` when the user sends their next message. Do NOT use `while/sleep` loops.

```
GET /auth/claim?magic=a8f3k9x2m5p7...

Response (payment complete):
{
  "status": "ready",
  "token": "eyJhbG...",
  "expires_at": "2026-04-05T10:00:00Z",
  "user": { "id": 892, "email": "user@example.com", "name": "user" }
}

Response (still waiting):
{ "status": "pending", "message": "Waiting for payment completion" }

Response (expired - 1 hour timeout):
{ "status": "expired", "message": "Magic token expired" }
```

- Payment processing can take up to 90 seconds after the user pays.
- The magic token is valid for 1 hour total.
- If still `pending` after several minutes, ask the user if they completed the payment.

**Persist the token!** Once you receive the token, save it so you can reuse it for future interactions with this user's servers. If you lose it, the user will need to re-authenticate. Store the token in a secure location — environment variables, a secret manager, or an agent-private memory store. Never write tokens into files that are committed to version control (e.g., AGENTS.md, config files in git repos).

### Step 5: Pick a region and install

```
GET /catalog/regions

Response: { regions: [
    { id: "ne",  name: "North America - East" },
    { id: "w",   name: "North America - West" },
    { id: "ew",  name: "Europe" },
    { id: "as",  name: "Australia" }
  ]}
```

Recommend the closest region based on the user's location. If you already know where the user is (from conversation context), pick the closest one directly without asking. General guidance:
- Western Europe → `ew`
- Eastern US / Canada → `ne`
- Western US → `w`
- Asia-Pacific / Oceania → `as`

Then:

```
GET /servers
Authorization: Bearer {token}
```

This returns the user's server(s). After purchase there will be one server in `PENDING` status. Install the game:

```
POST /servers/{id}/install
Authorization: Bearer {token}
Body: { "game": "vlh", "region": "ew", "branch": "stable" }

Response: { "status": "INSTALLING" }
```

### Step 6: Wait for installation

Poll the server status until it's ready:

```
GET /servers/{id}
Authorization: Bearer {token}
```

The status progression is: `PENDING` → `INSTALLING` → `STARTED`

Poll every 8-10 seconds. Installation typically takes 1-3 minutes. Keep the user informed:
> "Installing Valheim on Europe server... this usually takes a couple of minutes."

### Step 7: Deliver connection details

Once status is `STARTED`:

```
GET /servers/{id}/connection
Authorization: Bearer {token}

Response: {
  "sub_id": 42,
  "deployment": { "uuid": "d-abc123", "game": "vlh", "status": "STARTED", ... },
  "server_data": {
    "address": "eu1.supercraft.host",
    "game_port": 10342,
    "connection_string": "eu1.supercraft.host:10342",
    "password": "k7m2x9",
    ...
  }
}
```

Tell the user exactly how to connect, specific to their game. Example for Valheim:

> **Your Valheim server is ready!**
> - Open Valheim → Join Game → Add Server
> - Address: `eu1.supercraft.host:10342`
> - Password: `k7m2x9`
>
> Share these details with your friends!

### Step 8: Offer to customize

Ask if they want to:
- Change server name or password
- Adjust game settings
- Set up any game-specific options

If yes, read the config schema first to know what's available:

```
GET /servers/{id}/config/schema
```

Then read current config, modify, save, and restart:

```
GET /servers/{id}/config
PUT /servers/{id}/config  { "config": { "name": "My Server", "password": "newpass" } }
POST /servers/{id}/restart
```

Always restart after config changes - the server needs to reload.

---

## Workflow 2: Existing user needs help

The user already has an account and a server.

### Authentication

Ask the user for their Supercraft account email. Then generate a login link:

```
POST /auth/login-link
Body: { "email": "user@example.com" }

Response: {
  "magic": "b7k2m9x5p3...",
  "login_url": "https://supercraft.host/my-account/?magic=b7k2m9x5p3...",
  "claim_endpoint": "/auth/claim?magic=b7k2m9x5p3...",
  "expires_in_seconds": 3600
}
```

⚠️ **Send the login link to the user NOW — before calling any tools.** Your reply must contain the `login_url`. Do not start polling or run any commands before the message is delivered.

> Please click this link to verify your identity: https://supercraft.host/my-account/?magic=b7k2m9x5p3...

**After** the user receives the link, set up a cron job to poll `GET /auth/claim?magic=b7k2m9x5p3...` every 30 seconds. If cron is not available, poll when the user sends their next message. Do NOT use `while/sleep` loops. Once the user logs in, the magic token is fulfilled and you receive your API token.

```
GET /auth/claim?magic=b7k2m9x5p3...

Response (user logged in):
{
  "status": "ready",
  "token": "eyJhbG...",
  "user": { "id": 172, "email": "user@example.com", "name": "John" }
}
```

**Persist the token!** Save it securely (environment variable, secret manager, or agent-private memory — never in version-controlled files) so you don't need to re-authenticate next time.

### If the user forgot their password

```
POST /auth/reset-password
Body: { "email": "user@example.com" }

Response: { "status": "ok", "message": "Password reset email sent if account exists" }
```

This sends a real WordPress password reset email. Tell the user:
> A password reset email has been sent — check your inbox (and spam folder). Once you've set a new password, click the login link I gave you earlier and we'll continue.

### Common tasks

**Check server status:**
```
GET /servers
GET /servers/{id}
```

**Start/stop/restart:**
```
POST /servers/{id}/start
POST /servers/{id}/stop
POST /servers/{id}/restart
```

These return `202` with a task status. Poll `GET /servers/{id}` to watch progress.

**Change settings:**
```
GET /servers/{id}/config/schema    ← what options exist
GET /servers/{id}/config           ← current values
PUT /servers/{id}/config           ← update
POST /servers/{id}/restart         ← apply changes
```

**Send console command (if game supports it):**
```
POST /servers/{id}/console
Body: { "command": "say Hello everyone!" }
```

**View logs:**
```
GET /servers/{id}/logs?lines=100
```

**Get connection info:**
```
GET /servers/{id}/connection
```

---

## Workflow 3: Switch to a different game

Users can switch their server to any supported game included in their plan.

**Step 1:** Check what games are available for this server's plan:

```
GET /servers/{id}/available-games
→ { "available_games": [{ "application_id": "vlh", "name": "Valheim", "branches": ["stable", "experimental"] }, ...] }
```

**Step 2:** Switch to the desired game (requires region):

```
POST /servers/{id}/switch-game
Body: { "game": "mc", "region": "ew", "branch": "stable" }
```

This wipes the current game data, provisions a new deployment, and installs the new game. Poll `GET /servers/{id}` for status updates.

**Warning:** This is destructive — all current game data is permanently deleted. Always warn the user and get confirmation before switching.

---

## Understanding Server States

| Status | Meaning | What you can do |
|--------|---------|-----------------|
| `PENDING` | Provisioned but no game installed | Install a game |
| `INSTALLING` | Game being installed | Wait (poll for updates) |
| `INSTALLED` | Game installed, not running | Start the server |
| `STARTING` | Server booting up | Wait |
| `STARTED` | Running and playable | Stop, restart, configure |
| `STOPPING` | Shutting down | Wait |
| `STOPPED` | Not running | Start, configure, switch game |
| `BROKEN_INSTALL` | Installation failed | Retry install or contact support |
| `BROKEN_START` | Failed to start | Check logs, fix config, retry |

**Important:** Config schema, config read/write, start, stop, restart, console, and logs are only available once the game has finished installing. While the server is in `PENDING` or `INSTALLING` state, these endpoints will return `409`. Wait for the status to reach `STARTED`, `STOPPED`, or `INSTALLED` before using them.

When you see a `BROKEN_*` state, read the logs (`GET /servers/{id}/logs`) and look for error messages. Common fixes:
- Bad config value → read schema, fix config, restart
- Port conflict → usually resolves on retry
- Game update issue → try reinstalling

---

## Error Handling

**HTTP status codes:**
- `200` - Success
- `201` - Created
- `202` - Accepted (async operation started, poll for result)
- `400` - Bad request (check your parameters)
- `401` - Not authenticated (need Bearer token)
- `403` - Forbidden (token expired or wrong user)
- `404` - Not found
- `409` - Conflict (e.g., server already running, can't start again)
- `429` - Rate limited (wait and retry)

**Error response format:**
```json
{
  "error": "ERROR_CODE",
  "message": "Human-readable description"
}
```

**When things go wrong:**
1. If auth fails (401/403): re-authenticate using `POST /auth/login-link` with the user's email, then poll `/auth/claim`
2. If user can't log in: trigger `POST /auth/reset-password` and guide them through password reset
3. If server is stuck in a state: check logs, try stop then start
4. If installation fails: try wipe + reinstall
5. If nothing works: tell the user to contact support via Discord or email at contact@supercraft.host

---

## Rate Limits

- Anonymous endpoints: 30 requests/minute
- Authenticated endpoints: 120 requests/minute
- Server operations (start/stop/restart): 10 per minute per server
- Status polling: don't poll more than once every 5 seconds

---

## Tips for Good Agent Behavior

1. **Persist the API token securely.** Save the Bearer token to a secure location — environment variables, a secret manager, or agent-private memory. Never write tokens into files committed to version control. If the token is lost, the user has to re-authenticate.
2. **Send link first, then poll.** When you get a `checkout_url` or `login_url`, your immediate next action MUST be a message to the user — not a tool call. If you call `exec`, `curl`, or set up a cron before replying, the link message will never be delivered. After the link is sent, use a cron job (every 30 seconds) to poll `/auth/claim`. Never use `while/sleep` loops.
3. **Bust caches on non-catalog requests.** Some agent platforms cache HTTP responses. To ensure fresh data on auth, server status, and config endpoints, append `&_t=<unix_timestamp>` (or `?_t=<unix_timestamp>` if no query string) to your requests. Example: `GET /auth/claim?magic=TOKEN&_t=1709912345`. Catalog endpoints (`/catalog/*`) are cached for 1 hour and don't need this.
4. **Don't poll server status too aggressively.** 8-10 second intervals for status checks is fine.
5. **Always confirm destructive actions** with the user before executing (wipe, switch game).
6. **Read the config schema** before suggesting settings changes - each game has different options.
7. **Give specific connection instructions** for the game, not just raw IP:port. Include step-by-step instructions for the specific game client.
8. **If you're unsure about a game's features**, read `GET /catalog/games/{game_code}` before giving advice.

---

## Supported Games

| Game | Code | Plans | Offer Details |
|------|------|-------|---------------|
| Valheim | `vlh` | L, M, S | [Plans & Pricing](/dedicated-servers/valheim-server-hosting-offer.md) |
| Satisfactory | `stf` | L, M, S | [Plans & Pricing](/dedicated-servers/satisfactory-server-hosting-offer.md) |
| Palworld | `pal` | L, M, S | [Plans & Pricing](/dedicated-servers/palworld-server-hosting-offer.md) |
| Enshrouded | `ens` | L, M, S | [Plans & Pricing](/dedicated-servers/enshrouded-server-hosting-offer.md) |
| Project Zomboid | `prz` | L, M, S | [Plans & Pricing](/dedicated-servers/project-zomboid-server-hosting-offer.md) |
| Factorio | `fac` | L, M, S | [Plans & Pricing](/dedicated-servers/factorio-server-hosting-offer.md) |
| V-Rising | `vrs` | L, M, S | [Plans & Pricing](/dedicated-servers/v-rising-server-hosting-offer.md) |
| Vintage Story | `vst` | L, M, S | [Plans & Pricing](/dedicated-servers/vintage-story-server-hosting-offer.md) |
| Necesse | `nec` | L, M, S | [Plans & Pricing](/dedicated-servers/necesse-server-hosting-offer.md) |
| Terraria | `ter` | L, M, S | [Plans & Pricing](/dedicated-servers/terraria-server-hosting-offer.md) |
| Unturned | `unt` | L, M, S | [Plans & Pricing](/dedicated-servers/unturned-server-hosting-offer.md) |
| Hytale | `hyt` | L, M, S | [Plans & Pricing](/dedicated-servers/hytale-server-hosting-offer.md) |
| Counter-Strike 2 | `cs2` | L, M, S | [Plans & Pricing](/dedicated-servers/counter-strike-2-server-hosting-offer.md) |
| Rust | `rst` | L, M, S | [Plans & Pricing](/dedicated-servers/rust-server-hosting-offer.md) |
| Humanitz | `hmz` | L, M, S | [Plans & Pricing](/dedicated-servers/humanitz-server-hosting-offer.md) |
| Sons of the Forest | `sof` | M | [Plans & Pricing](/dedicated-servers/sons-of-the-forest-server-hosting-offer.md) |
| ARK: Survival Ascended | `arksa` | L, M, S | [Plans & Pricing](/dedicated-servers/ark-survival-ascended-server-hosting-offer.md) |
| FiveM | `fiv` | L, M, S | [Plans & Pricing](/dedicated-servers/fivem-server-hosting-offer.md) |
| Minecraft Bedrock | `mcb` | L, M, S | [Plans & Pricing](/dedicated-servers/minecraft-bedrock-server-hosting-offer.md) |
| Minecraft Java | `mnj` | L, M, S | [Plans & Pricing](/dedicated-servers/minecraft-java-server-hosting-offer.md) |
| Icarus | `ics` | L, M, S | [Plans & Pricing](/dedicated-servers/icarus-server-hosting-offer.md) |
| Farming Simulator 25 | `fs25` | L, M, S | [Plans & Pricing](/dedicated-servers/farming-simulator-25-server-hosting-offer.md) |
| The Forest | `tfo` | L, M, S | [Plans & Pricing](/dedicated-servers/the-forest-server-hosting-offer.md) |
| Echoes of Elysium | `eoe` | L, M, S | [Plans & Pricing](/dedicated-servers/echoes-of-elysium-server-hosting-offer.md) |
| Windrose | `wnd` | L, M, S | [Plans & Pricing](/dedicated-servers/windrose-server-hosting-offer.md) |

---
*[supercraft.host](https://supercraft.host) — Game Server Hosting Platform*
