---
title: Realtime SDK Reference
description: Real-time subscriptions and messaging with the InsForge Swift SDK
---

import SwiftSdkInstallation from '/snippets/swift-sdk-installation.mdx';

## Installation

<SwiftSdkInstallation />

## connect()

Establish a WebSocket connection to the realtime server.

### Example

```swift
do {
    try await insforge.realtime.connect()
    print("Connected to realtime server")
} catch {
    print("Connection failed: \(error)")
}
```

---

## subscribe()

Subscribe to a channel to receive messages.

### Parameters

- `to` (String) - Channel name (e.g., "orders:123", "chat:room-1")
- `onMessage` (Closure) - Callback for receiving messages

### Example

```swift
await insforge.realtime.subscribe(to: "chat:lobby") { message in
    print("Event: \(message.eventName ?? "")")
    print("Channel: \(message.channelName ?? "")")

    if let payload = message.payload {
        print("Data: \(payload)")
    }

    if let senderId = message.senderId {
        print("From: \(senderId)")
    }
}
```

---

## unsubscribe()

Unsubscribe from a channel.

### Example

```swift
await insforge.realtime.unsubscribe(from: "chat:lobby")
```

---

## publish()

Publish a message to a channel.

### Parameters

- `to` (String) - Channel name
- `event` (String) - Event name
- `payload` ([String: Any]) - Message payload as dictionary

### Example

```swift
try await insforge.realtime.publish(
    to: "chat:lobby",
    event: "message.new",
    payload: [
        "text": "Hello everyone!",
        "author": currentUser.name,
        "timestamp": Date().timeIntervalSince1970
    ]
)
```

---

## disconnect()

Disconnect from the realtime server.

### Example

```swift
await insforge.realtime.disconnect()
```

---

## Channel API

The high-level Channel API provides a more structured way to work with realtime features including broadcast messages and Postgres changes.

### channel()

Get or create a channel instance.

```swift
let channel = await insforge.realtime.channel("chat:lobby")
```

### removeChannel()

Remove a channel.

```swift
await insforge.realtime.removeChannel("chat:lobby")
```

---

## RealtimeChannel

### subscribe()

Subscribe to the channel. Must be called before receiving messages.

```swift
let channel = await insforge.realtime.channel("chat:lobby")
try await channel.subscribe()
```

### unsubscribe()

Unsubscribe from the channel.

```swift
await channel.unsubscribe()
```

---

## Broadcast Messages

### Listening for Broadcasts

Use `broadcast(event:)` to receive broadcast messages as an AsyncStream.

```swift
let channel = await insforge.realtime.channel("chat:lobby")
try await channel.subscribe()

// Listen for specific event
for await message in await channel.broadcast(event: "new_message") {
    print("Event: \(message.event)")
    print("Payload: \(message.payload)")

    // Decode to typed struct
    if let chatMessage = try? message.decode(ChatMessage.self) {
        print("Message: \(chatMessage.text)")
    }
}

// Listen for all events (wildcard)
for await message in await channel.broadcast(event: "*") {
    print("Received: \(message.event)")
}
```

### Sending Broadcasts

Send broadcast messages with typed or dictionary payloads.

```swift
// With Encodable struct
struct ChatMessage: Codable {
    let text: String
    let author: String
}

try await channel.broadcast(
    event: "new_message",
    message: ChatMessage(text: "Hello!", author: "John")
)

// With dictionary
try await channel.broadcast(
    event: "typing",
    message: ["userId": userId, "isTyping": true]
)
```

---

## Postgres Changes

Listen for real-time database changes using typed actions.

### Action Types

- `InsertAction<T>` - New record inserted
- `UpdateAction<T>` - Record updated (includes `record` and `oldRecord`)
- `DeleteAction<T>` - Record deleted (includes `oldRecord`)
- `SelectAction<T>` - Record selected
- `AnyAction<T>` - Any of the above

### Listening for Changes

```swift
struct Todo: Codable, Sendable {
    let id: String
    let title: String
    let completed: Bool
}

let channel = await insforge.realtime.channel("db-changes")
try await channel.subscribe()

// Listen for inserts only
for await action in await channel.postgresChange(
    InsertAction<Todo>.self,
    schema: "public",
    table: "todos"
) {
    print("New todo: \(action.record.title)")
}

// Listen for any change
for await action in await channel.postgresChange(
    AnyAction<Todo>.self,
    schema: "public",
    table: "todos"
) {
    switch action {
    case .insert(let insert):
        print("Inserted: \(insert.record.title)")
    case .update(let update):
        print("Updated: \(update.record.title)")
    case .delete(let delete):
        print("Deleted: \(delete.oldRecord.title)")
    case .select(let select):
        print("Selected: \(select.record.title)")
    }
}
```
