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

# Realtime Messages

> A message is a named handler with typed inputs, a function stack, and a response — an API endpoint applied to a websocket.

<Info>
  This page covers the current version of Realtime. In [Realtime (Legacy)](/realtime/realtime-in-xano), a message is an opaque payload broadcast to the channel, and the only place logic can run is a single channel trigger.
</Info>

## What a message is

A **message** is the invocable handler inside a channel. It is the Realtime equivalent of an API endpoint, and it has the same parts:

| Part               | Purpose                                                               |
| ------------------ | --------------------------------------------------------------------- |
| **Payload schema** | The typed inputs the message accepts                                  |
| **Middleware**     | Pre- and post-processing shared across handlers                       |
| **Function stack** | Your logic — database work, external calls, anything else Xano can do |
| **Response**       | What is sent back                                                     |
| **`deliver_to`**   | Which clients receive the result                                      |

Because a message is a named handler rather than an untyped broadcast, the client sends *"invoke `send` with this payload"* rather than *"push these bytes to everyone on the channel."*

## Payload schema

Every message declares the payload it accepts, with types, exactly the way an API endpoint declares its inputs. Xano validates the incoming payload against that schema **before any of your logic runs** — a malformed payload is rejected at the boundary, not halfway through a function stack that has already written to your database.

This is the single biggest practical difference from legacy Realtime, where the payload is whatever the client sent and validating it is your job inside the trigger.

## In XanoScript

A message names **both** the server and the channel it belongs to, because a channel path is unique only within its server.

```java XanoScript lines icon="code" theme={null}
message "send" {
  realtime_server = "chat"
  channel = "rooms/{room_id}"
  deliver_to = "channel"
  description = "Broadcast a chat message to everyone in the room"
  history = "inherit"

  input {
    text body
  }

  stack {
    db.add "chat_message" {
      data = {body: $input.body, user_id: $auth.id}
    } as $row
  }

  response = {ok: true, id: $row.id}

  tags = ["chat"]
}
```

`realtime_server`, `channel`, `input`, `stack`, and `response` are required. `deliver_to`, `description`, `history`, `middleware`, and `tags` are optional.

## The function stack

From the payload onward, a message is an ordinary Xano function stack. Everything you use in an API endpoint is available: database queries, custom functions, external API requests, conditionals, loops, and middleware.

You also get the same authoring tools:

* **Canvas, stack, XanoScript, and split-screen** editing
* **DB Preview**, to see the effect of database steps while you build
* **Run & Debug**, to execute a message handler without attaching a client
* **Drafts and publish**, so a half-finished handler isn't live
* **Branches, diffs, and version history**

## Delivery

`deliver_to` is chosen **per message** and decides who receives the result:

| Value      | Who receives it                               |
| ---------- | --------------------------------------------- |
| `channel`  | Everyone on the channel                       |
| `sender`   | Just the client that invoked the message      |
| `others`   | The rest of the channel, excluding the sender |
| `explicit` | A set of clients you target                   |

<Tip>
  `deliver_to = "sender"` turns a websocket into a request/response channel. The client invokes a message, your stack does the work, and the result comes back over the same open connection — no second HTTP round trip, and no fan-out to clients that don't care.
</Tip>

The **guarantee** for those deliveries — `at_most_once` or `at_least_once` — is a channel setting rather than a message one. See [Delivery guarantees](/realtime/realtime-servers-and-channels#delivery-guarantees).

### Rewriting a delivery per recipient

Delivery isn't all-or-nothing. A channel's **deliver** trigger runs once per recipient and can rewrite or drop that individual copy — so one publish becomes N personalized or redacted deliveries. See [Realtime Triggers](/realtime/realtime-triggers#channel-scope).

## Requiring authentication

A message can **require authentication** independently of whether the channel allows anonymous clients to join. That means a channel can be open to read — anonymous clients join and receive broadcasts — while the messages that write to it are restricted to authenticated clients.

Because it's per message, one channel can mix them: a `typing` indicator open to everyone, and a `send` handler that isn't. See [Access Control](/realtime/access-control).

## Observability

Message executions appear in [Request History](/maintenance-monitoring-and-logging/request-history) under a **Messages** tab. Retention is set per object with the `history` clause, which accepts `false`, `"inherit"`, a record count (`0`, `10`, `100`, `1000`, `10000`), or `"all"`.

## Next steps

<CardGroup cols={2}>
  <Card title="Realtime Triggers" icon="bolt" href="/realtime/realtime-triggers">
    Run logic on connect, disconnect, join, leave, and deliver.
  </Card>

  <Card title="Publishing from Xano" icon="tower-broadcast" href="/realtime/publishing-from-xano">
    Push to a channel from any query, function, or task.
  </Card>
</CardGroup>


## Related topics

- [Realtime In Xano (Legacy)](/realtime/realtime-in-xano.md)
- [Publishing to a Channel from Xano](/realtime/publishing-from-xano.md)
- [2024 Release Notes](/updates/2024.md)
