> ## 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.

# Publishing to a Channel from Xano

> realtime.publish injects a server-authored event onto a channel from any query, function, or task.

<Info>
  This page covers the current version of Realtime. For the legacy **Realtime Event** function, see [Realtime Functions (Legacy)](/the-function-stack/functions/apis-and-lambdas/realtime-functions).
</Info>

Not every realtime update starts with a client. Often the thing that changed is on the server: an order shipped, a background job finished, a nightly aggregation produced new numbers.

**`realtime.publish`** injects a server-authored event onto a channel from anywhere in Xano — a query, a custom function, or a scheduled task. The clients on that channel receive it over their existing connection, with no polling and no client-side request.

## Publish in the visual editor

In a function stack, add **Realtime Publish** from **APIs & Lambdas**, or search for it by name. It is the visual editor equivalent of `realtime.publish`.

| Panel field                              | XanoScript        | What to enter                                            |
| ---------------------------------------- | ----------------- | -------------------------------------------------------- |
| **Realtime Server**                      | `realtime_server` | Server name, such as `chat`; not its WebSocket canonical |
| **Channel**                              | `channel`         | Resolved path, such as `rooms/42`                        |
| **Message** (optional)                   | `message`         | Outgoing frame's `type`, such as `announcement`          |
| **Data**                                 | `data`            | Payload delivered to subscribers                         |
| **Authentication → Database** (optional) | `auth_table`      | Table used for identity attribution                      |
| **Authentication → Row ID** (optional)   | `auth_id`         | Attributed record ID; shown after selecting a database   |

Realtime Server and Channel accept constants, variables, and expressions. Autocomplete offers workspace server names and channel templates as suggestions; it does not restrict values to that list. Resolve a template such as `rooms/{room_id}` to `rooms/42` before publishing. A channel path belongs to a particular server, so supply both fields. If suggestions fail to load, you can still enter the values directly.

**Message does not invoke a message handler.** Publishing with `message = "send"` delivers your Data as-is with `type: "send"`; it does not run the `send` handler's input validation, function stack, or per-message authentication. Authorize the calling API or stack before publishing. The optional Authentication fields attach identity metadata only; they do not validate credentials or grant access.

### Availability and version choice

**Realtime Publish** requires Realtime V2 support on the instance. In the picker category and search results, it is greyed out with an explanation when V2 is unavailable. An empty autocomplete list is a separate issue and does not mean V2 is disabled.

**Realtime Event (v1)** remains available for legacy connections. Its XanoScript statement is `api.realtime_event`. It cannot reach V2 subscribers and can complete without an error while delivering nothing to them. Do not substitute it when Realtime Publish is unavailable; check V2 availability on the instance instead.

## `realtime.publish`

| Argument          | Required | Meaning                                                                                      |
| ----------------- | -------- | -------------------------------------------------------------------------------------------- |
| `realtime_server` | **Yes**  | Target server, by name                                                                       |
| `channel`         | **Yes**  | Target channel, as a **resolved path** — `"rooms/42"`, not the template `"rooms/{room_id}"`  |
| `data`            | **Yes**  | The payload                                                                                  |
| `message`         | No       | Sets the delivered frame's `type`, which is what a client's receive handler discriminates on |
| `auth_table`      | No       | Asserted identity, for attribution                                                           |
| `auth_id`         | No       | Asserted identity, for attribution                                                           |
| `description`     | No       | Authoring annotation                                                                         |
| `disabled`        | No       | Authoring annotation                                                                         |

<Warning>
  `auth_table` and `auth_id` are **attribution only**. They stamp an identity onto the event so recipients can see who it came from — they do **not** authenticate anything and are not an access-control mechanism. Enforce access with [channel settings and triggers](/realtime/access-control).
</Warning>

`realtime.publish` returns nothing, so it takes no `as $variable` binding.

### Example

```java XanoScript lines icon="code" theme={null}
function "broadcast_announcement" {
  input {
    text body
  }

  stack {
    realtime.publish {
      realtime_server = "chat"
      channel = "rooms/42"
      message = "announcement"
      data = {body: $input.body}
    }
  }

  response = {ok: true}
}
```

## `realtime.get_session`

`realtime.get_session` reads the current realtime execution context; it is not needed to publish from an ordinary API or function. It takes no required arguments and requires an `as $variable` binding. See the [message handler example](/realtime/connecting-a-client#create-an-echo-handler) for use inside a realtime message.

## Where you can publish from

| Source               | Typical use                                                                   |
| -------------------- | ----------------------------------------------------------------------------- |
| **API endpoint**     | An action taken over REST fans out to everyone watching the affected resource |
| **Custom function**  | Shared publish logic reused across several stacks                             |
| **Scheduled task**   | A recurring job feeds a live dashboard                                        |
| **Database trigger** | A table change pushes an update to subscribers of that record                 |

## Patterns

### Notification and dashboard channels

Set the channel's `publish.who` to `nobody`. Clients join and listen but can never send, and every update on the channel comes from a stack you control. This is the cleanest shape for notifications, status feeds, and live dashboards.

### Broadcast after a database write

Write the record first, then publish. Persisting before publishing means a client that joins after the fact — and reads the channel [transcript](/realtime/realtime-servers-and-channels#conversation-transcript) or queries your table — sees the same thing as one that was connected the whole time.

### Progress and streaming

A long-running task can publish incremental updates on a channel keyed to the job, so the client sees progress rather than a spinner. The same pattern streams an LLM or agent response back over the connection as it's produced.

<Tip>
  Keep payloads small. Publishing an ID and a changed field, and letting the client fetch details when it needs them, keeps fan-out cheap — especially on a channel with many listeners or a [deliver trigger](/realtime/realtime-triggers#channel-scope) that runs per recipient.
</Tip>

## Publishing vs. a message handler

Both put data on a channel, but they start from different places:

|                                | Message                               | `realtime.publish`                  |
| ------------------------------ | ------------------------------------- | ----------------------------------- |
| **Started by**                 | A connected client invoking a handler | Any Xano stack                      |
| **Has a payload schema**       | Yes                                   | No — you build the payload          |
| **Delivery targeting**         | Per-message `deliver_to`              | The channel                         |
| **Appears in Request History** | Yes, under Messages                   | As part of the stack that published |

Use a message when the client is asking for something. Use `realtime.publish` when Xano has something to tell the client.

<Note>
  **`realtime.publish` is not `api.realtime_event`.** The Realtime Event function (`api.realtime_event`, shown as **Realtime Event (v1)** in the statement picker) belongs to [Realtime (Legacy)](/realtime/realtime-in-xano). They are different statements targeting different systems — a legacy channel can't be reached with `realtime.publish`, and a v2 channel can't be reached with `api.realtime_event`.
</Note>

## Verify delivery

Connect two V2 clients to the same server and resolved channel, and wait for both join acknowledgements. Run the publishing stack and confirm both receive an `action: "message"` frame with `type: "announcement"` and the supplied payload. A successful stack or HTTP response alone does not prove delivery. See [Connecting a Client](/realtime/connecting-a-client).

## Next steps

<CardGroup cols={2}>
  <Card title="Messages" icon="message" href="/realtime/messages">
    Client-invoked handlers, and delivery targeting.
  </Card>

  <Card title="Servers & Channels" icon="signal-stream" href="/realtime/realtime-servers-and-channels">
    Channel path templates, settings, and transcript.
  </Card>
</CardGroup>


## Related topics

- [Realtime Functions (Legacy)](/the-function-stack/functions/apis-and-lambdas/realtime-functions.md)
- [Realtime](/realtime/overview.md)
- [Update realtime channel details using XanoScript](/api-reference/realtime/update-realtime-channel-details-using-xanoscript.md)
