> ## Documentation Index
> Fetch the complete documentation index at: https://docs.playflowcloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# REST API Reference

> Authenticate, manage game servers, upload builds, and configure projects using the PlayFlow Cloud REST API.

The PlayFlow Cloud API gives you full programmatic control over your game server infrastructure. You can start and stop servers, upload and manage builds, configure project settings, and monitor server health -- all through standard HTTP requests.

The API is designed for consumption by game clients, backend services, CI/CD pipelines, and AI agents alike. Every endpoint returns predictable JSON with machine-readable status fields and clear error messages.

<Card title="Full OpenAPI Reference" icon="book-open" href="/api-reference/introduction">
  Explore the interactive API reference with schemas, parameters, and try-it-out functionality for every endpoint.
</Card>

## Prerequisites

Before you make your first request, make sure you have:

* A PlayFlow account with an organization and a project.
* An API key for that project (found under **Project Settings** in the dashboard). Use a **Server API Key** (`pf_*`) for backend and CI/CD calls, or a **Client API Key** (`pfclient_*`) for code that ships to players.
* A processed build (`status: ready`) if you plan to start servers -- see [Upload a Build](#upload-a-build).

<Info>
  Deleting builds and updating project settings require a **Server API Key**. A Client API Key receives a `403` on those operations.
</Info>

***

## Authentication

All API endpoints (except `/api/health`) require an API key passed via the `api-key` HTTP header.

```bash theme={null}
curl https://api.computeflow.cloud/api/v3/servers \
  -H "api-key: pf_your_server_api_key"
```

### API Key Types

PlayFlow projects have two API keys, each with a different access level:

| Key Type       | Prefix       | Access Level                   | Use Case                             |
| :------------- | :----------- | :----------------------------- | :----------------------------------- |
| Server API Key | `pf_*`       | Full read/write                | Backend services, CI/CD, admin tools |
| Client API Key | `pfclient_*` | Limited client-safe operations | Game clients, browser apps           |

<Info>
  You can find and regenerate your API keys in the [PlayFlow Dashboard](https://app.playflowcloud.com) under **Project Settings**.
</Info>

<Warning>
  Never expose your **Server API Key** in client-side code or public repositories. Use the **Client API Key** for any code that ships to players.
</Warning>

***

## Base URL

All API requests are made to:

```
https://api.computeflow.cloud/api
```

The canonical API version is **v3**. A v2 compatibility layer is available for legacy SDKs but all new integrations should target v3.

| Version        | Path Prefix | Notes                                              |
| :------------- | :---------- | :------------------------------------------------- |
| V3 (canonical) | `/api/v3/*` | Zod-validated, OpenAPI spec, clean response shapes |
| V2 (legacy)    | `/api/v2/*` | Compatibility layer for older SDKs                 |

***

## Endpoints Overview

### Servers

Manage the full lifecycle of your game servers -- create, inspect, update, restart, and stop.

| Method   | Endpoint                           | Description                       |
| :------- | :--------------------------------- | :-------------------------------- |
| `GET`    | `/v3/servers`                      | List servers for your project     |
| `POST`   | `/v3/servers/start`                | Launch a new game server          |
| `GET`    | `/v3/servers/:instance_id`         | Get details for a specific server |
| `POST`   | `/v3/servers/:instance_id/update`  | Update a server's `custom_data`   |
| `DELETE` | `/v3/servers/:instance_id`         | Stop a running server             |
| `POST`   | `/v3/servers/:instance_id/restart` | Restart a server                  |
| `GET`    | `/v3/servers/:instance_id/logs`    | Retrieve server logs              |
| `GET`    | `/v3/servers/:instance_id/metrics` | Retrieve server resource metrics  |

### Builds

Upload game server binaries and manage the build pipeline.

| Method   | Endpoint                    | Description                        |
| :------- | :-------------------------- | :--------------------------------- |
| `GET`    | `/v3/builds`                | List builds for your project       |
| `POST`   | `/v3/builds/upload-url`     | Get a presigned URL for ZIP upload |
| `POST`   | `/v3/builds/docker-image`   | Create a build from a Docker image |
| `GET`    | `/v3/builds/:build_id`      | Get build details                  |
| `DELETE` | `/v3/builds/:build_id`      | Soft-delete a build                |
| `GET`    | `/v3/builds/:build_id/logs` | Get build processing logs          |

### Projects

Read and update project-level configuration, and query logs across all servers.

| Method | Endpoint                | Description                   |
| :----- | :---------------------- | :---------------------------- |
| `GET`  | `/v3/projects/settings` | Get project configuration     |
| `POST` | `/v3/projects/settings` | Update project configuration  |
| `GET`  | `/v3/projects/logs`     | Query logs across all servers |

***

## Common Operations

### List Servers

Retrieve all running servers for your project. By default, only servers with status `running` are returned.

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.computeflow.cloud/api/v3/servers?include_launching=true&limit=20" \
    -H "api-key: pf_your_server_api_key"
  ```

  ```csharp C# theme={null}
  using var client = new HttpClient();
  client.DefaultRequestHeaders.Add("api-key", "pf_your_server_api_key");

  var response = await client.GetAsync(
      "https://api.computeflow.cloud/api/v3/servers?include_launching=true&limit=20"
  );
  var json = await response.Content.ReadAsStringAsync();
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://api.computeflow.cloud/api/v3/servers",
      headers={"api-key": "pf_your_server_api_key"},
      params={"include_launching": "true", "limit": 20},
  )
  data = response.json()
  ```
</CodeGroup>

**Query parameters:**

<ParamField query="include_launching" type="boolean" default="false">
  Include servers that are still in the `launching` state.
</ParamField>

<ParamField query="include_pool" type="boolean" default="false">
  Include pre-warmed pool servers in the results. Pre-warmed pooling is not currently enabled, so this filter returns nothing today; every server cold-starts on demand.
</ParamField>

<ParamField query="limit" type="integer" default="50">
  Maximum number of servers to return (1-100).
</ParamField>

<ParamField query="offset" type="integer" default="0">
  Number of servers to skip for pagination.
</ParamField>

**Response:**

```json theme={null}
{
  "total": 3,
  "total_servers": 3,
  "servers": [
    {
      "instance_id": "abc123",
      "name": "us-east-lobby-1",
      "status": "running",
      "region": "us-east",
      "compute_size": "small",
      "version_tag": "default",
      "version": 4,
      "network_ports": [
        {
          "name": "game",
          "internal_port": 7777,
          "external_port": 30412,
          "protocol": "udp",
          "host": "37.16.24.10",
          "tls_enabled": false
        }
      ],
      "started_at": "2026-03-15T10:30:00.000Z",
      "stopped_at": null,
      "custom_data": { "map": "arena_01" },
      "ttl": 3600,
      "is_pool_server": false,
      "match_id": null,
      "auto_restart": false,
      "created_at": "2026-03-15T10:29:55.000Z",
      "updated_at": "2026-03-15T10:30:00.000Z"
    }
  ],
  "limit": 50,
  "offset": 0,
  "has_more": false
}
```

***

### Start a Server

Launch a new game server instance. The server is provisioned immediately and moves through `launching` to `running` status.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.computeflow.cloud/api/v3/servers/start" \
    -H "api-key: pf_your_server_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "us-east-lobby-1",
      "region": "us-east",
      "compute_size": "small",
      "version_tag": "default",
      "ttl": 3600,
      "custom_data": {
        "map": "arena_01",
        "max_players": 16
      }
    }'
  ```

  ```csharp C# theme={null}
  using var client = new HttpClient();
  client.DefaultRequestHeaders.Add("api-key", "pf_your_server_api_key");

  var body = new StringContent(
      JsonSerializer.Serialize(new {
          name = "us-east-lobby-1",
          region = "us-east",
          compute_size = "small",
          version_tag = "default",
          ttl = 3600,
          custom_data = new { map = "arena_01", max_players = 16 }
      }),
      Encoding.UTF8,
      "application/json"
  );

  var response = await client.PostAsync(
      "https://api.computeflow.cloud/api/v3/servers/start", body
  );
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.computeflow.cloud/api/v3/servers/start",
      headers={
          "api-key": "pf_your_server_api_key",
          "Content-Type": "application/json",
      },
      json={
          "name": "us-east-lobby-1",
          "region": "us-east",
          "compute_size": "small",
          "version_tag": "default",
          "ttl": 3600,
          "custom_data": {"map": "arena_01", "max_players": 16},
      },
  )
  server = response.json()
  print(f"Instance ID: {server['instance_id']}")
  ```
</CodeGroup>

**Request body:**

<ParamField body="name" type="string" required>
  A display name for the server instance.
</ParamField>

<ParamField body="region" type="string" required>
  The deployment region. See [Server Regions](/fundamentals/regions) for the full list.
</ParamField>

<ParamField body="compute_size" type="string" default="small">
  Server instance size. One of: `micro`, `small`, `medium`, `large`, `xlarge`, `dedicated-small`, `dedicated-medium`, `dedicated-large`, `dedicated-xlarge`. See [Pricing & Plan Types](/fundamentals/plan-instance-types) for specs.
</ParamField>

<ParamField body="version_tag" type="string">
  The build name to deploy. Defaults to the latest build if not specified.
</ParamField>

<ParamField body="version" type="integer">
  A specific build version number. If omitted, the latest version for the given `version_tag` is used.
</ParamField>

<ParamField body="startup_args" type="string">
  Command-line arguments passed to your game server executable on launch.
</ParamField>

<ParamField body="ttl" type="integer">
  Time-to-live in seconds (60-86400). The server automatically stops after this duration.
</ParamField>

<ParamField body="auto_restart" type="boolean" default="false">
  If `true`, the server restarts automatically if the game process exits.
</ParamField>

<ParamField body="custom_data" type="object">
  Arbitrary key-value data attached to the server. Useful for passing map names, game modes, or match metadata to your game server at runtime.
</ParamField>

<ParamField body="match_id" type="string">
  An optional match identifier to associate this server with a specific match or lobby.
</ParamField>

<ParamField body="environment_variables" type="object">
  Key-value string pairs set as environment variables on the server instance.
</ParamField>

<ParamField body="port_configs" type="array">
  Override the project-level port configuration for this server. Each entry specifies a `name`, `internal_port`, `protocol` (`udp` or `tcp`), and optional `tls_enabled` flag.
</ParamField>

**Response (201 Created):**

```json theme={null}
{
  "instance_id": "abc123",
  "name": "us-east-lobby-1",
  "status": "launching",
  "region": "us-east",
  "compute_size": "small",
  "version_tag": "default",
  "version": 4,
  "network_ports": [
    {
      "name": "game",
      "internal_port": 7777,
      "external_port": 30412,
      "protocol": "udp",
      "host": "37.16.24.10",
      "tls_enabled": false
    }
  ],
  "startup_args": null,
  "service_type": "match_based",
  "started_at": null,
  "stopped_at": null,
  "auto_restart": false,
  "custom_data": { "map": "arena_01", "max_players": 16 },
  "ttl": 3600,
  "is_pool_server": false,
  "pool_claimed_at": null,
  "match_id": null,
  "created_at": "2026-03-15T10:29:55.000Z",
  "updated_at": "2026-03-15T10:29:55.000Z"
}
```

<Info>
  The server starts in `launching` status. Once the game process is ready, the status changes to `running` and `started_at` is populated. You can poll `GET /v3/servers/:instance_id` or use `include_launching=true` when listing servers to track this transition.
</Info>

<Warning>
  Always read the connection host and port from `network_ports[]` in the live API response -- never hardcode them. The proxy allocates a fresh `external_port` per server (it is not the same as your `internal_port`, and it is not a fixed value like `7777`). TCP ports resolve through a relay hostname (`relay.computeflow.cloud`); UDP ports return a raw proxy IPv4 address. Read `host` + `external_port` together for each port your client needs.
</Warning>

***

### Stop a Server

Shut down a running server and release its resources.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE "https://api.computeflow.cloud/api/v3/servers/abc123" \
    -H "api-key: pf_your_server_api_key"
  ```

  ```python Python theme={null}
  response = requests.delete(
      "https://api.computeflow.cloud/api/v3/servers/abc123",
      headers={"api-key": "pf_your_server_api_key"},
  )
  ```
</CodeGroup>

**Query parameters:**

<ParamField query="shutdown_reason" type="string">
  An optional reason for stopping the server, recorded for logging purposes.
</ParamField>

**Response:**

The `status` field is a human-readable confirmation message, not a state enum -- do not branch on it matching `"stopped"`.

```json theme={null}
{
  "status": "Server stopped successfully"
}
```

***

### Upload a Build

Uploading a build is a two-step process: request a presigned upload URL, then upload your ZIP file. Processing starts automatically when the upload finishes.

<Steps>
  <Step title="Request an upload URL">
    Call the upload-url endpoint to get a presigned R2 URL and a `build_id`.

    The `executable_path` query parameter is optional. If omitted, PlayFlow runs `Server.x86_64` inside your ZIP. Set it when your server binary has a different name.

    ```bash theme={null}
    curl -X POST "https://api.computeflow.cloud/api/v3/builds/upload-url?name=default&executable_path=GameServer.x86_64" \
      -H "api-key: pf_your_server_api_key"
    ```

    **Response (201 Created):**

    ```json theme={null}
    {
      "build_id": "build_abc123",
      "name": "default",
      "upload_url": "https://r2.cloudflarestorage.com/...",
      "message": "Upload URL generated. PUT your ZIP to upload_url within 60 minutes."
    }
    ```

    The presigned `upload_url` expires 60 minutes after it is issued.
  </Step>

  <Step title="Upload your ZIP file">
    Use the presigned URL to upload your game server build as a ZIP archive. Processing begins automatically once the upload completes.

    ```bash theme={null}
    curl -X PUT "https://r2.cloudflarestorage.com/..." \
      -H "Content-Type: application/zip" \
      --data-binary @my-game-server.zip
    ```
  </Step>

  <Step title="Poll for status">
    Poll `GET /v3/builds/{build_id}` until `status` is `ready` (or `failed`).

    ```bash theme={null}
    curl "https://api.computeflow.cloud/api/v3/builds/build_abc123" \
      -H "api-key: pf_your_server_api_key"
    ```
  </Step>
</Steps>

You can track build progress by polling `GET /v3/builds/:build_id` or by streaming build logs from `GET /v3/builds/:build_id/logs`.

***

### Create a Build from Docker Image

If you already have a containerized game server, you can create a build directly from a Docker image instead of uploading a ZIP.

```bash theme={null}
curl -X POST "https://api.computeflow.cloud/api/v3/builds/docker-image" \
  -H "api-key: pf_your_server_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "default",
    "image_url": "ghcr.io/my-org/game-server:latest",
    "executable_path": "/app/GameServer",
    "registry_credentials": {
      "username": "my-user",
      "password": "my-token"
    }
  }'
```

<ParamField body="name" type="string" default="default">
  The build name (used as the `version_tag` when starting servers).
</ParamField>

<ParamField body="image_url" type="string" required>
  The full Docker image URL including tag.
</ParamField>

<ParamField body="executable_path" type="string">
  Path to the game server executable inside the container.
</ParamField>

<ParamField body="registry_credentials" type="object">
  Credentials for private registries. Include `username` and `password` fields.
</ParamField>

***

## Response Shapes

### Server Object

Every server endpoint returns or includes the following shape:

<Expandable title="Server response fields">
  <ResponseField name="instance_id" type="string">
    Unique identifier for the server instance.
  </ResponseField>

  <ResponseField name="name" type="string">
    Display name of the server.
  </ResponseField>

  <ResponseField name="status" type="string">
    Current server state: `launching`, `running`, or `stopped`.
  </ResponseField>

  <ResponseField name="network_ports" type="array">
    List of port mappings. Each entry contains `name`, `internal_port`, `external_port`, `protocol`, `host`, and `tls_enabled`.
  </ResponseField>

  <ResponseField name="startup_args" type="string | null">
    Command-line arguments passed to the game server.
  </ResponseField>

  <ResponseField name="service_type" type="string">
    Either `match_based` or `persistent_world`.
  </ResponseField>

  <ResponseField name="compute_size" type="string">
    Instance size (e.g., `small`, `large`, `dedicated-medium`).
  </ResponseField>

  <ResponseField name="region" type="string">
    Deployment region identifier.
  </ResponseField>

  <ResponseField name="version_tag" type="string">
    The build name deployed on this server.
  </ResponseField>

  <ResponseField name="version" type="integer | null">
    The build version number, if applicable.
  </ResponseField>

  <ResponseField name="started_at" type="string | null">
    ISO 8601 timestamp when the server became `running`. Null while `launching`.
  </ResponseField>

  <ResponseField name="stopped_at" type="string | null">
    ISO 8601 timestamp when the server was stopped.
  </ResponseField>

  <ResponseField name="auto_restart" type="boolean">
    Whether the server restarts automatically on process exit.
  </ResponseField>

  <ResponseField name="custom_data" type="object | null">
    Arbitrary metadata attached to the server.
  </ResponseField>

  <ResponseField name="ttl" type="integer | null">
    Time-to-live in seconds, if set.
  </ResponseField>

  <ResponseField name="is_pool_server" type="boolean">
    Whether this server was provisioned from the pre-warmed pool. Pre-warmed pooling is not currently enabled, so this is always `false` today.
  </ResponseField>

  <ResponseField name="pool_claimed_at" type="string | null">
    ISO 8601 timestamp when a pool server was claimed. Always `null` while pooling is disabled.
  </ResponseField>

  <ResponseField name="match_id" type="string | null">
    Associated match or lobby identifier.
  </ResponseField>

  <ResponseField name="created_at" type="string">
    ISO 8601 timestamp when the instance record was created.
  </ResponseField>

  <ResponseField name="updated_at" type="string">
    ISO 8601 timestamp of the last update.
  </ResponseField>
</Expandable>

### Build Object

<Expandable title="Build response fields">
  <ResponseField name="build_id" type="string">
    Unique identifier for the build.
  </ResponseField>

  <ResponseField name="name" type="string">
    Build name, used as the `version_tag` when starting servers.
  </ResponseField>

  <ResponseField name="version" type="integer">
    Auto-incremented version number within this build name.
  </ResponseField>

  <ResponseField name="status" type="string">
    Build state: `uploading`, `processing`, `ready`, `failed`, or `deleted`.
  </ResponseField>

  <ResponseField name="build_type" type="string">
    Either `zip` (uploaded archive) or `docker_image`.
  </ResponseField>

  <ResponseField name="executable_path" type="string | null">
    Path to the game server executable.
  </ResponseField>

  <ResponseField name="image_url" type="string | null">
    Docker image URL, if the build was created from a container image.
  </ResponseField>

  <ResponseField name="created_at" type="string">
    ISO 8601 timestamp when the build was created.
  </ResponseField>

  <ResponseField name="updated_at" type="string | null">
    ISO 8601 timestamp of the last update.
  </ResponseField>
</Expandable>

***

## Server Logs and Metrics

### Server Logs

Retrieve stdout/stderr logs from a running or recently stopped server.

```bash theme={null}
curl "https://api.computeflow.cloud/api/v3/servers/abc123/logs?limit=100" \
  -H "api-key: pf_your_server_api_key"
```

<ParamField query="start_time" type="string">
  ISO 8601 timestamp to begin retrieving logs from.
</ParamField>

<ParamField query="end_time" type="string">
  ISO 8601 timestamp to stop retrieving logs at.
</ParamField>

<ParamField query="search" type="string">
  Filter to log lines containing this substring.
</ParamField>

<ParamField query="level" type="string">
  Filter by log level (e.g. `info`, `warn`, `error`).
</ParamField>

<ParamField query="limit" type="integer" default="1000">
  Number of log entries to return (1-1000).
</ParamField>

**Response:**

```json theme={null}
{
  "logs": [
    {
      "timestamp": "2026-03-15T10:30:05.123Z",
      "message": "Server started on port 7777",
      "level": "info",
      "instance": "abc123",
      "region": "us-east"
    }
  ],
  "instance_id": "abc123",
  "machine_id": "fly-machine-id",
  "next_token": null,
  "older_token": null
}
```

### Server Metrics

Retrieve CPU, memory, network, and connection metrics for a running server.

```bash theme={null}
curl "https://api.computeflow.cloud/api/v3/servers/abc123/metrics?period=1h&step=60s" \
  -H "api-key: pf_your_server_api_key"
```

<ParamField query="period" type="string" default="1h">
  Time window for metrics. One of: `5m`, `15m`, `1h`, `6h`, `24h`.
</ParamField>

<ParamField query="step" type="string" default="60s">
  Resolution between data points. One of: `15s`, `30s`, `60s`, `300s`.
</ParamField>

**Response:**

```json theme={null}
{
  "instance_id": "abc123",
  "machine_id": "fly-machine-id",
  "region": "us-east",
  "period": {
    "start": 1742036400,
    "end": 1742040000,
    "step": "60s"
  },
  "cpu": {
    "usage_percent": [{ "t": 1742036400, "v": 12.5 }]
  },
  "memory": {
    "used_mb": [{ "t": 1742036400, "v": 256 }],
    "total_mb": 1024
  },
  "network": {
    "rx_bytes_per_sec": [{ "t": 1742036400, "v": 1024 }],
    "tx_bytes_per_sec": [{ "t": 1742036400, "v": 2048 }]
  },
  "load": {
    "average_1m": [{ "t": 1742036400, "v": 0.5 }]
  },
  "connections": {
    "tcp": [{ "t": 1742036400, "v": 8 }]
  }
}
```

***

## Error Handling

All error responses share a consistent JSON structure:

```json theme={null}
{
  "error": "Human-readable error message",
  "detail": "Same as error (for legacy SDK compatibility)",
  "status": 400
}
```

### Common Status Codes

| Status | Meaning                                                              |
| :----- | :------------------------------------------------------------------- |
| `200`  | Success                                                              |
| `201`  | Resource created (server started, upload URL generated)              |
| `202`  | Accepted (build processing triggered)                                |
| `401`  | Missing or invalid `api-key` header                                  |
| `404`  | Server, build, or resource not found                                 |
| `422`  | Validation error (malformed request body or missing required fields) |
| `429`  | Rate limit exceeded                                                  |
| `500`  | Internal server error                                                |

### Validation Errors

When request validation fails, the response includes structured error details:

```json theme={null}
{
  "error": "Validation error",
  "detail": [
    {
      "loc": ["region"],
      "msg": "Required",
      "type": "invalid_type"
    }
  ],
  "status": 422
}
```

***

## Rate Limiting

The API uses token-bucket rate limiting per API key. Rate limit status is returned in response headers.

| Endpoint Type                                | Limit               |
| :------------------------------------------- | :------------------ |
| Read endpoints (list, get, logs, metrics)    | 100 requests/second |
| Write endpoints (start server, upload build) | 10 requests/second  |

**Response headers:**

| Header                  | Description                        |
| :---------------------- | :--------------------------------- |
| `X-RateLimit-Limit`     | Maximum tokens in the bucket       |
| `X-RateLimit-Remaining` | Tokens remaining before throttling |

When the rate limit is exceeded, you receive a `429` response:

```json theme={null}
{
  "error": "Rate limit exceeded",
  "detail": "Rate limit exceeded. Please retry after a short wait.",
  "status": 429
}
```

***

## Regions

Deploy your servers across 13 global regions for low-latency gameplay. Pass any of these region IDs to the `region` field when starting a server.

| Region                     | ID                     |
| :------------------------- | :--------------------- |
| US East                    | `us-east`              |
| US South (Dallas)          | `us-south`             |
| US West                    | `us-west`              |
| Europe North (Sweden)      | `eu-north`             |
| Europe West (Germany)      | `eu-west`              |
| Europe (United Kingdom)    | `eu-uk`                |
| Asia South (India)         | `ap-south`             |
| Southeast Asia (Singapore) | `sea`                  |
| Asia North (Japan)         | `ap-north`             |
| Australia                  | `ap-southeast`         |
| South Africa               | `south-africa`         |
| South America (Brazil)     | `south-america-brazil` |
| South America (Chile)      | `south-america-chile`  |

See [Server Regions](/fundamentals/regions) for the full details on each region.

***

## SDK and Tooling

<CardGroup cols={2}>
  <Card title="Unity SDK" icon="gamepad" href="/unity/programmatic-access">
    Use the PlayFlow Unity SDK for C# wrappers around the REST API, including server management from your game client.
  </Card>

  <Card title="Interactive API Reference" icon="flask-vial" href="/api-reference/introduction">
    Explore every endpoint with the full OpenAPI specification, request/response schemas, and a try-it-out console.
  </Card>
</CardGroup>
