# Roblox SDK

The complete client, session, event, and type reference for the BirdHouse Matchmaking Luau SDK on Roblox servers.

Source: https://birdhouse.tech/docs/roblox-sdk/

The server-side SDK manages ticket creation, batched heartbeats, cancellation, and reconciliation for Roblox experiences. Install it through [Wally](https://birdhouse.tech/docs/installation/).

## MatchmakingClient.new

```luau
local client = MatchmakingClient.new({
    baseUrl = "https://matchmaking.example.com",
    environment = "prod",
    heartbeatSeconds = 5,
})
```

| Option | Type | Required | Meaning |
| --- | --- | --- | --- |
| `baseUrl` | `string` | Yes | HTTP(S) service base URL, without `/api/progress`, query, or fragment. Trailing slashes are removed. |
| `environment` | `string` | Yes | Valid environment key allowed by the service. |
| `heartbeatSeconds` | `number` | No | Default `5`; must be finite, greater than zero, and less than `300`. |

Leave enough heartbeat margin for request latency and multiple batches. The SDK has no token or custom-header setting.

## client:CreateSession

```luau
local session = client:CreateSession({
    players = {
        { id = "123456789" },
        { id = "987654321" },
    },
    meta = { mode = "squads", skill = 1200 },
    constraints = {
        type = "and",
        constraints = {
            { type = "playerCount", min = 4, max = 4 },
            { type = "fieldEqualsDeep", field = "mode" },
        },
    },
})
```

| Option | Type | Required | Meaning |
| --- | --- | --- | --- |
| `players` | `Player[]` | Yes | A nonempty party with unique player IDs. |
| `constraints` | `Constraint` | No | The ticket's matching rule tree. |
| `meta` | string-keyed table | No | JSON-compatible ticket metadata used by field rules. |

A player has a string `id` and optional JSON-compatible `meta`. IDs must contain 1–32 UTF-16 code units; use `tostring(player.UserId)`.

This method does not yield. It validates synchronously, copies options, and defers network work. Invalid input throws without creating a session. An `environment` field in session options is rejected; configure it on the client.

## Session properties

| Property | Type | Meaning |
| --- | --- | --- |
| `State` | `SessionState` | Current local lifecycle state. |
| `TicketId` | `string` | GUID assigned before submission; retained for correlation. |
| `Match` | `Match?` | Retained successful outcome. |
| `Error` | `SDKError?` | Retained terminal failure. |

Treat properties as read-only. `TicketId` does not prove service acceptance. `SessionState` is one of `pending`, `matching`, `canceling`, `matched`, `canceled`, and `failed`.

## Events

### session.Matched

Fires with a validated `Match`. The SDK stores `session.Match` before firing the event and sends terminal `StateChanged` afterward.

```luau
session.Matched:Connect(function(match)
    for _, ticket in match.tickets do
        for _, player in ticket.players do
            print("Matched player", player.id)
        end
    end
end)
```

### session.Failed

Fires with the terminal `SDKError`, after it is stored in `session.Error` and before terminal `StateChanged`.

### session.StateChanged

Fires on state transitions. The initial `pending` state is available as a property but is not emitted as an event. Terminal states are `matched`, `canceled`, and `failed`.

### client.Error

Reports request and protocol errors. A retryable error can leave sessions active while the SDK reconciles or retries work. It is different from a session's terminal `Failed` event.

Connect immediately after creation. Events do not replay for late listeners. Session signals are disconnected after terminal delivery, and callback completion is not awaited between events.

## Cancellation and destruction

`session:Cancel()` requests cancellation and is idempotent. It may finish an unsent session locally or enter `canceling` while awaiting the service. A match can still win.

`client:Destroy()` abandons the client immediately. Active sessions end as `failed` with `client_destroyed`; new work stops. It is not a graceful cancel/drain operation. See [ticket lifecycle](https://birdhouse.tech/docs/lifecycle/).

## Match and ticket types

```luau
export type Match = {
    id: string,
    environment: string?,
    tickets: { Ticket },
    meta: { [string]: any }?,
}

export type Ticket = {
    id: string,
    environment: string?,
    players: { Player },
    createdAt: number,
    status: number,
    matchId: string?,
    constraints: Constraint?,
    meta: { [string]: any }?,
    traceparent: string?,
}
```

`createdAt` is an epoch timestamp in milliseconds. Environments are optional in response types for legacy results. Use session lifecycle states for normal integration logic; raw ticket status values are described in the [HTTP reference](https://birdhouse.tech/docs/http-api/).

## Exported types

The module exports `Constraint`, `Player`, `Ticket`, `Match`, `CreateOptions`, `SessionState`, `Session`, `ClientConfig`, `MatchmakingClient`, and `SDKError`.

`SDKError` contains `code`, `message`, `retryable`, optional `statusCode`, and optional `details`. Response details can include submitted data and are not automatically logged. See [errors and recovery](https://birdhouse.tech/docs/errors/).
