# auth.md: Falix

You are an agent. Falix (game and app server hosting) supports **agentic registration**: discover, register, claim if needed, exchange for an access token, call the API. Follow the steps in order.

- API (resource): `https://client.falixnodes.net/api/v2`
- Authorization server: `https://client.falixnodes.net/api/v2`
- API reference: `https://client.falixnodes.net/api/v2/docs` and `https://client.falixnodes.net/api/v2/llms.txt`
- MCP server: `https://client.falixnodes.net/api/v2/mcp` (send the same access token as a Bearer header)

## Ground rules

- **Ask your user before anything destructive.** Before you delete a server, reinstall one, restore a backup, wipe files or stop a server players are on, tell your user exactly what will happen and wait for a clear yes. Falix additionally asks the account owner to approve every server deletion and every purchase on a page you cannot click for them.
- **Never solve a captcha or approve a purchase yourself.** Hand the link to your user.
- **Never ask your user for their Falix password, 2FA codes or card details.** You never need them.
- Keep `claim_token` in memory only for the claim ceremony. Never write access tokens or identity assertions to logs or files your user did not ask for.

## Step 1: Discover

`GET https://client.falixnodes.net/api/v2/.well-known/oauth-protected-resource`, then `GET https://client.falixnodes.net/api/v2/.well-known/oauth-authorization-server`. Read `agent_auth.identity_types_supported` to see which registration methods are enabled. Any `401` from the API carries the same pointer:

```http
WWW-Authenticate: Bearer resource_metadata="https://client.falixnodes.net/api/v2/.well-known/oauth-protected-resource"
```

## Step 2: Pick a method

1. You can mint an ID-JAG for your user from a provider Falix trusts, with `aud` = `https://client.falixnodes.net/api/v2`: use `identity_assertion` (only when it is listed in `identity_types_supported`).
2. You know your user's email: use `service_auth`. Your user signs in at Falix and types a code you give them.
3. You know nothing about your user yet: use `anonymous`. You get a temporary Falix account straight away and can run one free server on it. Your user can claim it later; **unclaimed accounts and their servers are deleted after 7 days.**

Before `identity_assertion` or `service_auth`, tell your user that you are about to connect to their Falix account and confirm they want that.

## Step 3: Register

```http
POST https://client.falixnodes.net/api/v2/agent/identity
Content-Type: application/json

{ "type": "service_auth", "login_hint": "user@example.com" }
```

Other bodies: `{ "type": "anonymous" }` and `{ "type": "identity_assertion", "assertion_type": "urn:ietf:params:oauth:token-type:id-jag", "assertion": "<ID-JAG>" }`.

- `service_auth` answers with `claim_token` and a `claim` block (`user_code`, `verification_uri`, `expires_in`, `interval`). Go to step 4b.
- `anonymous` answers with an `identity_assertion` (go to step 5) plus a `claim_token` for later.
- `identity_assertion` answers with an `identity_assertion` (step 5). If the email belongs to an existing Falix account it answers `401 interaction_required` with a `claim` block instead: the account owner must confirm the link (step 4b). `401 login_required` means your user's login at your provider is older than an hour: re-authenticate them there and mint a fresh ID-JAG.

## Step 4: Claim ceremony

### 4a. Start a claim (anonymous only, or to get a fresh code)

```http
POST https://client.falixnodes.net/api/v2/agent/identity/claim
Content-Type: application/json

{ "claim_token": "clm_...", "email": "user@example.com" }
```

Only the person signed in to Falix with that email can complete the claim. On success the anonymous account's server moves into their account.

### 4b. Hand off to your user

Send your user one message with the link and the code, for example:

> Open this link, sign in to Falix (or create an account with this email), and enter the code **123456**: https://...

The code goes into the Falix page, not back to you. Codes expire after 10 minutes; ask for a new one with step 4a (same `claim_token` and email).

### 4c. Poll

```http
POST https://client.falixnodes.net/api/v2/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=clm_...
```

`authorization_pending`: keep waiting, every `interval` seconds (`slow_down`: wait longer). `expired_token`: the code or the claim window expired; start again at 4a, or at step 3 if 4a answers `claim_expired`. Success returns an `access_token` and a new `identity_assertion`; drop any earlier ones. The claim token works for exactly one successful poll.

## Step 5: Exchange the assertion

```http
POST https://client.falixnodes.net/api/v2/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<identity_assertion>
```

The answer has an `access_token` (`fxag_...`) valid for `expires_in` seconds (one hour). There is no refresh token: when it expires, exchange the same `identity_assertion` again. When that returns `invalid_grant`, the connection was closed (your user disconnected you, or it expired); start again at step 3.

## Step 6: Call the API

```http
GET https://client.falixnodes.net/api/v2/servers
Authorization: Bearer fxag_...
```

The access token works on every `https://client.falixnodes.net/api/v2` endpoint its scopes allow and on the MCP server (step 7). A temporary (unclaimed) account can only manage its own servers; after a claim you act on your user's whole account, except that you can never add SSH keys, subusers or support access.

### Approvals

Some requests wait for a human. They answer `403` with `error.code` set to:

- `approval_required`: `error.action_url` is a link for your user. A free server needs a quick human check; a purchase or a server deletion needs the account owner's OK. Give your user the link, poll `error.approval.status_url` (`GET`, same Bearer token) until `status` is `approved`, then send **exactly the same request again** within 10 minutes. It runs once.
- `approval_pending`: an approval for this exact request is already waiting. Keep polling its `status_url`; do not ask your user again.

`rejected` means your user said no: do not retry, ask them what they want instead.

## Step 7: Add the Falix MCP server (if you don't have it)

Falix has an MCP server with tools for servers, files, console, backups, billing and the rest of the API: `https://client.falixnodes.net/api/v2/mcp` (Streamable HTTP, Bearer auth). If your client supports MCP and you have no Falix tools yet, add it with your access token. Ask your user first if adding it changes their client's config.

Claude Code:

```bash
claude mcp add --transport http falix https://client.falixnodes.net/api/v2/mcp --header "Authorization: Bearer fxag_..."
```

OpenAI Codex (CLI and IDE extension), with the token in the `FALIX_ACCESS_TOKEN` environment variable Codex starts with:

```bash
codex mcp add falix --url https://client.falixnodes.net/api/v2/mcp --bearer-token-env-var FALIX_ACCESS_TOKEN
```

That writes this to `~/.codex/config.toml`; the token itself stays out of the file:

```toml
[mcp_servers.falix]
url = "https://client.falixnodes.net/api/v2/mcp"
bearer_token_env_var = "FALIX_ACCESS_TOKEN"
```

Gemini CLI (writes the project's `.gemini/settings.json`; add `-s user` for `~/.gemini/settings.json`):

```bash
gemini mcp add --transport http --header "Authorization: Bearer fxag_..." falix https://client.falixnodes.net/api/v2/mcp
```

VS Code (GitHub Copilot agent mode), in `.vscode/mcp.json`:

```json
{
  "servers": {
    "falix": {
      "type": "http",
      "url": "https://client.falixnodes.net/api/v2/mcp",
      "headers": { "Authorization": "Bearer fxag_..." }
    }
  }
}
```

Cursor (`~/.cursor/mcp.json`) and other clients that read an `mcpServers` file:

```json
{
  "mcpServers": {
    "falix": {
      "url": "https://client.falixnodes.net/api/v2/mcp",
      "headers": { "Authorization": "Bearer fxag_..." }
    }
  }
}
```

Access tokens last an hour. When Falix tools start answering `401`, exchange your identity assertion again (step 5) and update the header (in Codex, the variable, then restart Codex). If your client cannot do that, call the REST API directly instead; it takes the same token.

## Revocation

`POST https://client.falixnodes.net/api/v2/oauth2/revoke` with `token=<access_token>` revokes one access token. Your user can disconnect you at any time from their Falix profile (API keys, Connected AI agents); everything you hold then stops working.

## Errors

| Code | Where | What to do |
| --- | --- | --- |
| `anonymous_not_enabled` | `/agent/identity` | Pick another method. |
| `issuer_not_enabled` | `/agent/identity` | Your provider is not trusted. Use `service_auth` or `anonymous`. |
| `invalid_request` | anywhere | Fix the request body. |
| `interaction_required` (401) | `/agent/identity` | Hand the `claim` block to your user (step 4b). |
| `login_required` (401) | `/agent/identity` | Re-authenticate at your provider, mint a fresh ID-JAG. |
| `invalid_claim_token` / `claim_expired` / `claimed_or_in_flight` | `/agent/identity/claim` | Restart at step 3. |
| `authorization_pending` / `slow_down` / `expired_token` | `/oauth2/token` | See step 4c. |
| `invalid_grant` | `/oauth2/token` | Restart at step 3. |
| `rate_limited` (429) | anywhere | Back off and retry after `Retry-After`. |
