---
source_url: https://www.pubnub.com/docs/sdks/c/api-reference/mobile-push
title: Mobile Push API for C SDK
updated_at: 2026-09-24T12:25:41.000Z
sdk_name: PubNub C SDK
sdk_version: 1.0.0
---

# Mobile Push API for C SDK

PubNub C SDK, use the latest version: 1.0.0

## Documentation index

To discover more PubNub resources:

1. Fetch [PubNub's llms.txt](https://www.pubnub.com/llms-full.txt) for a list of available pages in Markdown format.
2. Identify relevant URLs from that index.
3. Fetch the target pages.

Do not assume a path exists, always check the index first.

Mobile Push Notifications connects PubNub channel traffic to Apple Push Notification service over HTTP/2 (APNS2) and Firebase Cloud Messaging (FCM). This page covers **device registration only**: associating a push token with one or more channels so that PubNub knows which devices to notify. `pubnub_push_add_channels()`, `pubnub_push_remove_channels()`, `pubnub_push_list_channels()`, and `pubnub_push_remove_device()` are the whole public API for this feature. No function anywhere in the SDK sends or builds a push notification.

To deliver a notification, publish a message whose JSON body contains a `pn_apns` and/or `pn_fcm` key, using the ordinary [publish](https://www.pubnub.com/docs/sdks/c/api-reference/publish-and-subscribe.md#publish) call. When PubNub finds one of those reserved keys in a published message, it looks up every device registered on that channel through the functions on this page and forwards the corresponding payload to APNs or FCM. The SDK does not validate or build the `pn_apns`/`pn_fcm` payload shape for you. Construct it yourself, as part of the JSON string you already pass to `pubnub_publish()`:

```c
#include <pubnub/client.h>
#include <pubnub/features/publish.h>
#include <pubnub/future.h>

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    pubnub_config_t cfg = pubnub_config_defaults();
    cfg.publish_key   = "demo";
    cfg.subscribe_key = "demo";
    cfg.user_id       = "my_unique_user_id";

    pubnub_context_t* ctx = pubnub_create(&cfg);
    if (NULL == ctx) {
        return EXIT_FAILURE;
    }

    pubnub_publish_opts_t opts = PUBNUB_PUBLISH_OPTS_INIT;
    opts.channel = "alerts";
    opts.message =
        "{"
        "\"text\":\"hello\","
        "\"pn_apns\":{\"aps\":{\"alert\":\"hello\"}},"
        "\"pn_fcm\":{\"notification\":{\"body\":\"hello\"}}"
        "}";

    pubnub_future_t future = pubnub_publish(ctx, &opts);
    while (!pubnub_future_is_ready(future)) {
        pubnub_process(ctx);
    }

    if (PUBNUB_OK != pubnub_future_status(future)) {
        fprintf(stderr, "publish failed\n");
    }

    pubnub_future_release(future);
    pubnub_destroy(ctx);
    return 0;
}
```

For the exact reserved-key payload shapes accepted by each provider, see [Push Basics](https://www.pubnub.com/docs/general/push/send.md), [iOS Mobile Push Notifications](https://www.pubnub.com/docs/general/push/ios.md), and [Android Mobile Push Notifications](https://www.pubnub.com/docs/general/push/android.md). Those pages describe a PubNub platform-wide convention, not something specific to this SDK.

:::note Requires Mobile Push Notifications add-on
Every function on this page requires that Mobile Push Notifications is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). See how to [enable add-on features](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-).
:::

All four functions share `#include <pubnub/features/push.h>`. Each is gated behind the `PUBNUB_ENABLE_PUSH_NOTIFICATIONS` build flag, takes a context plus a `const` pointer to its own options struct, and returns a `pubnub_future_t` by value. Release it exactly once with `pubnub_future_release()`, whichever consumption style you use (cooperative polling, `pubnub_await`, or `pubnub_async`; see [Status Events](https://www.pubnub.com/docs/sdks/c/status-events.md)).

## Add channels to a device

`pubnub_push_add_channels()` registers a device for push notifications on one or more channels.

### Method(s)

```c
#include <pubnub/features/push.h>

pubnub_future_t pubnub_push_add_channels(pubnub_context_t* ctx,
                                          const pubnub_push_add_channels_opts_t* opts);
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| device | const | Yes | `—` | Borrowed, NUL-terminated. Hexadecimal APNS device token or FCM registration token string. `NULL` or an empty string is rejected with `PUBNUB_ERR_INVALID_ARGUMENT`. No length limit is enforced. |
| gateway | pubnub_push_gateway_t | Yes | `—` | `PUBNUB_PUSH_APNS2` or `PUBNUB_PUSH_FCM`. |
| channels | const | Yes | `—` | Borrowed, NUL-terminated. A single comma-separated list (e.g. `"alerts,updates"`), not an array. `NULL` or an empty string is rejected with `PUBNUB_ERR_INVALID_ARGUMENT`. |
| topic | const | Optional | `—` | Borrowed, NUL-terminated. The APNs bundle identifier. |
| environment | pubnub_push_environment_t | Optional | `PUBNUB_PUSH_ENV_DEVELOPMENT` | Ignored for FCM. |
| timeout_ms | uint32_t | Optional | `0 (inherits pubnub_config_t::transaction_timeout_ms)` | Per-call timeout override. |

Zero-initialize with `PUBNUB_PUSH_ADD_CHANNELS_OPTS_INIT` (expands to `{0}`).

**C-family contract**

* **Header** — `#include <pubnub/features/push.h>`
* **Types** — `pubnub_push_add_channels_opts_t`, `pubnub_push_gateway_t`, `pubnub_push_environment_t`
* **Prerequisite** — an initialized context
* **Feature flag** — `PUBNUB_ENABLE_PUSH_NOTIFICATIONS`
* **Ownership / lifetime** — `ctx` and `opts` are borrowed; `device`, `channels`, and `topic` are borrowed, caller-owned strings that must remain valid for the duration of the call
* **Blocking** — never blocks; returns a `pubnub_future_t` immediately, possibly already in a terminal failed state (see below)

:::warning APNS2 and FCM enforce the topic/environment rule in opposite directions
Setting `gateway` to `PUBNUB_PUSH_APNS2` with `topic == NULL` fails **synchronously** with `PUBNUB_ERR_INVALID_ARGUMENT`. The function returns before any network request is sent, and `pubnub_future_is_ready()` is already `true`. The reverse is **not** an error. Setting `topic` and/or a non-default `environment` while `gateway` is `PUBNUB_PUSH_FCM` is accepted without complaint: the SDK silently ignores both fields and sends neither in the request. This asymmetry applies identically to every function on this page.
:::

### Sample code

```c
#include <pubnub/client.h>
#include <pubnub/features/push.h>
#include <pubnub/future.h>
#include <pubnub/response.h>

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    pubnub_config_t cfg = pubnub_config_defaults();
    cfg.subscribe_key = "demo";
    cfg.user_id       = "example-push-add";

    pubnub_context_t* ctx = pubnub_create(&cfg);
    if (NULL == ctx) {
        return EXIT_FAILURE;
    }

    pubnub_future_t future =
        pubnub_push_add_channels(ctx,
                                  &(pubnub_push_add_channels_opts_t){
                                      .device   = "dXh7YzE:APA91bGExample",
                                      .gateway  = PUBNUB_PUSH_FCM,
                                      .channels = "alerts,updates",
                                  });

    while (!pubnub_future_is_ready(future)) {
        pubnub_process(ctx);
    }

    if (PUBNUB_OK == pubnub_future_status(future)) {
        printf("Channels added for push\n");
    }
    else {
        pubnub_string_view_t err = pubnub_response_error_message(future);
        fprintf(stderr, "Failed: %.*s\n", (int)err.len, err.ptr);
    }

    pubnub_future_release(future);
    pubnub_destroy(ctx);
    return 0;
}
```

### Returns

There is no result struct or payload accessor for this operation. Success is signaled entirely by the future's status: `pubnub_future_status(future) == PUBNUB_OK`. On failure, call `pubnub_response_error_message()` (or `pubnub_response_service_error()` for full detail) before releasing the future. See [Retrieving server error detail](https://www.pubnub.com/docs/sdks/c/status-events.md#retrieving-server-error-detail).

### Other examples

#### Register an APNS2 device

`topic` is required whenever `gateway` is `PUBNUB_PUSH_APNS2`; `environment` defaults to `PUBNUB_PUSH_ENV_DEVELOPMENT` if left unset.

```c
pubnub_future_t register_apns2_device(pubnub_context_t* ctx)
{
    return pubnub_push_add_channels(ctx,
                                     &(pubnub_push_add_channels_opts_t){
                                         .device      = "apns-hex-device-token",
                                         .gateway     = PUBNUB_PUSH_APNS2,
                                         .channels    = "alerts",
                                         .topic       = "com.example.myapp",
                                         .environment = PUBNUB_PUSH_ENV_PRODUCTION,
                                     });
}
```

## List channels registered for a device

`pubnub_push_list_channels()` retrieves every channel currently registered for push notifications on a given device.

### Method(s)

```c
#include <pubnub/features/push.h>

pubnub_future_t pubnub_push_list_channels(pubnub_context_t* ctx,
                                           const pubnub_push_list_channels_opts_t* opts);

pubnub_push_list_channels_result_t
pubnub_push_list_channels_result(pubnub_future_t future);

pubnub_string_view_t pubnub_push_list_channels_result_channel_at(pubnub_future_t future,
                                                                  size_t index);
```

| Parameter | Description |
| --- | --- |
| `device` *Type: `const char*`Default: — | Borrowed, NUL-terminated. `NULL` or an empty string is rejected with `PUBNUB_ERR_INVALID_ARGUMENT`. |
| `gateway` *Type: `pubnub_push_gateway_t`Default: — | `PUBNUB_PUSH_APNS2` or `PUBNUB_PUSH_FCM`. |
| `topic`Type: `const char*`Default: — | Borrowed, NUL-terminated. |
| `environment`Type: `pubnub_push_environment_t`Default: `PUBNUB_PUSH_ENV_DEVELOPMENT` | Ignored for FCM. |
| `start`Type: `const char*`Default: `NULL` (first page) | Borrowed, NUL-terminated pagination cursor. |
| `count`Type: `uint16_t`Default: `0` (server default, typically 500) | Maximum `1000`. |
| `timeout_ms`Type: `uint32_t`Default: `0` (inherits `pubnub_config_t::transaction_timeout_ms`) | Per-call timeout override. |

Zero-initialize with `PUBNUB_PUSH_LIST_CHANNELS_OPTS_INIT` (expands to `{0}`).

**C-family contract**

* **Header** — `#include <pubnub/features/push.h>`
* **Types** — `pubnub_push_list_channels_opts_t`, `pubnub_push_list_channels_result_t`
* **Prerequisite** — an initialized context
* **Feature flag** — `PUBNUB_ENABLE_PUSH_NOTIFICATIONS`
* **Ownership / lifetime** — `ctx` and `opts` are borrowed; every `pubnub_string_view_t` returned by `pubnub_push_list_channels_result_channel_at()` is a **non-NUL-terminated view** into memory owned by the future, valid only until `pubnub_future_release()`
* **Blocking** — never blocks; returns a `pubnub_future_t` immediately

### Sample code

```c
#include <pubnub/client.h>
#include <pubnub/features/push.h>
#include <pubnub/future.h>
#include <pubnub/response.h>

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    pubnub_config_t cfg = pubnub_config_defaults();
    cfg.subscribe_key = "demo";
    cfg.user_id       = "example-push-list";

    pubnub_context_t* ctx = pubnub_create(&cfg);
    if (NULL == ctx) {
        return EXIT_FAILURE;
    }

    pubnub_future_t future =
        pubnub_push_list_channels(ctx,
                                   &(pubnub_push_list_channels_opts_t){
                                       .device  = "dXh7YzE:APA91bGExample",
                                       .gateway = PUBNUB_PUSH_FCM,
                                   });

    while (!pubnub_future_is_ready(future)) {
        pubnub_process(ctx);
    }

    if (PUBNUB_OK == pubnub_future_status(future)) {
        pubnub_push_list_channels_result_t result =
            pubnub_push_list_channels_result(future);
        printf("Registered channels (%u):\n", result.channel_count);
        for (uint32_t i = 0; i < result.channel_count; ++i) {
            pubnub_string_view_t ch =
                pubnub_push_list_channels_result_channel_at(future, (size_t)i);
            printf("  %.*s\n", (int)ch.len, ch.ptr);
        }
    }
    else {
        pubnub_string_view_t err = pubnub_response_error_message(future);
        fprintf(stderr, "Failed: %.*s\n", (int)err.len, err.ptr);
    }

    pubnub_future_release(future);
    pubnub_destroy(ctx);
    return 0;
}
```

### Returns

`pubnub_push_list_channels_result(future)` returns a `pubnub_push_list_channels_result_t` by value, zero-initialized if the future is invalid or not yet ready:

| Field | Type | Description |
| --- | --- | --- |
| `channel_count` | `uint32_t` | Number of channels registered for push on this device. |

`pubnub_push_list_channels_result_channel_at(future, index)` returns the channel name at the given zero-based index as a `pubnub_string_view_t`, or a zero-initialized (empty) view for an out-of-range index. Read every view you need before calling `pubnub_future_release()`. The view becomes invalid afterward.

### Other examples

#### List channels with an asynchronous callback

```c
#include <pubnub/client.h>
#include <pubnub/error.h>
#include <pubnub/features/push.h>
#include <pubnub/future.h>
#include <pubnub/response.h>

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

static volatile int s_done;

static void on_list_complete(pubnub_future_t future, pubnub_res_t status, void* user_data)
{
    (void)user_data;

    if (PUBNUB_OK == status) {
        pubnub_push_list_channels_result_t result =
            pubnub_push_list_channels_result(future);
        printf("channels (%u):\n", result.channel_count);
        for (uint32_t i = 0; i < result.channel_count; ++i) {
            pubnub_string_view_t ch =
                pubnub_push_list_channels_result_channel_at(future, (size_t)i);
            printf("  %.*s\n", (int)ch.len, ch.ptr);
        }
    }
    else {
        pubnub_string_view_t err = pubnub_response_error_message(future);
        fprintf(stderr, "failed: %s (%.*s)\n", pubnub_res_str(status), (int)err.len, err.ptr);
    }

    pubnub_future_release(future);
    s_done = 1;
}

int main(void)
{
    pubnub_config_t cfg = pubnub_config_defaults();
    cfg.subscribe_key = "demo";
    cfg.user_id       = "example-push-list-async";

    pubnub_context_t* ctx = pubnub_create(&cfg);
    if (NULL == ctx) {
        return EXIT_FAILURE;
    }

    pubnub_future_t future =
        pubnub_push_list_channels(ctx,
                                   &(pubnub_push_list_channels_opts_t){
                                       .device  = "dXh7YzE:APA91bGExample",
                                       .gateway = PUBNUB_PUSH_FCM,
                                   });

    pubnub_res_t rc = pubnub_async(future, on_list_complete, NULL);
    if (PUBNUB_OK != rc) {
        fprintf(stderr, "pubnub_async registration failed: %s\n", pubnub_res_str(rc));
        pubnub_future_release(future);
        pubnub_destroy(ctx);
        return EXIT_FAILURE;
    }

    while (!s_done) {
        /* On a threaded platform, a background thread drives I/O here.
           On embedded builds without threads, call pubnub_process(ctx)
           in this loop instead. */
    }

    pubnub_destroy(ctx);
    return 0;
}
```

On threaded platforms, a background thread drives I/O while you wait for the callback; on embedded builds without threads, replace the wait with a loop that calls `pubnub_process(ctx)`. The completion callback matches the SDK-wide `pubnub_async_cb_t` signature: `void (*)(pubnub_future_t future, pubnub_res_t status, void* user_data)`.

## Remove channels from a device

`pubnub_push_remove_channels()` unregisters a device from push notifications on the specific channels named in `channels`. The device stays registered on any channel not listed. To remove a device from every channel at once, use [Remove a device entirely](#remove-a-device-entirely) instead.

### Method(s)

```c
#include <pubnub/features/push.h>

pubnub_future_t
pubnub_push_remove_channels(pubnub_context_t*                         ctx,
                             const pubnub_push_remove_channels_opts_t* opts);
```

| Parameter | Description |
| --- | --- |
| `device` *Type: `const char*`Default: — | Borrowed, NUL-terminated. `NULL` or an empty string is rejected with `PUBNUB_ERR_INVALID_ARGUMENT`. |
| `gateway` *Type: `pubnub_push_gateway_t`Default: — | `PUBNUB_PUSH_APNS2` or `PUBNUB_PUSH_FCM`. |
| `channels` *Type: `const char*`Default: — | Borrowed, NUL-terminated. A single comma-separated list of the channels to unregister. `NULL` or an empty string is rejected with `PUBNUB_ERR_INVALID_ARGUMENT`. |
| `topic`Type: `const char*`Default: — | Borrowed, NUL-terminated. |
| `environment`Type: `pubnub_push_environment_t`Default: `PUBNUB_PUSH_ENV_DEVELOPMENT` | Ignored for FCM. |
| `timeout_ms`Type: `uint32_t`Default: `0` (inherits `pubnub_config_t::transaction_timeout_ms`) | Per-call timeout override. |

Zero-initialize with `PUBNUB_PUSH_REMOVE_CHANNELS_OPTS_INIT` (expands to `{0}`). The same [APNS2/FCM topic and environment rule](#add-channels-to-a-device) described above applies here unchanged.

**C-family contract**

* **Header** — `#include <pubnub/features/push.h>`
* **Types** — `pubnub_push_remove_channels_opts_t`, `pubnub_push_gateway_t`, `pubnub_push_environment_t`
* **Prerequisite** — an initialized context
* **Feature flag** — `PUBNUB_ENABLE_PUSH_NOTIFICATIONS`
* **Ownership / lifetime** — `ctx` and `opts` are borrowed; `device`, `channels`, and `topic` are borrowed, caller-owned strings
* **Blocking** — never blocks; returns a `pubnub_future_t` immediately

### Sample code

This sample demonstrates APNS2, the only combination that requires `topic`:

```c
#include <pubnub/client.h>
#include <pubnub/features/push.h>
#include <pubnub/future.h>
#include <pubnub/response.h>

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    pubnub_config_t cfg = pubnub_config_defaults();
    cfg.subscribe_key = "demo";
    cfg.user_id       = "example-push-remove";

    pubnub_context_t* ctx = pubnub_create(&cfg);
    if (NULL == ctx) {
        return EXIT_FAILURE;
    }

    pubnub_future_t future =
        pubnub_push_remove_channels(ctx,
                                     &(pubnub_push_remove_channels_opts_t){
                                         .device      = "apns-hex-device-token",
                                         .gateway     = PUBNUB_PUSH_APNS2,
                                         .channels    = "alerts",
                                         .topic       = "com.example.myapp",
                                         .environment = PUBNUB_PUSH_ENV_PRODUCTION,
                                     });

    while (!pubnub_future_is_ready(future)) {
        pubnub_process(ctx);
    }

    if (PUBNUB_OK == pubnub_future_status(future)) {
        printf("Channels removed from push\n");
    }
    else {
        pubnub_string_view_t err = pubnub_response_error_message(future);
        fprintf(stderr, "Failed: %.*s\n", (int)err.len, err.ptr);
    }

    pubnub_future_release(future);
    pubnub_destroy(ctx);
    return 0;
}
```

### Returns

There is no result struct or payload accessor for this operation. Success is signaled entirely by the future's status: `pubnub_future_status(future) == PUBNUB_OK`.

## Remove a device entirely

`pubnub_push_remove_device()` removes the device's push registration completely, for every channel it was ever registered on, regardless of which channels those were. There is no `channels` field on this operation's options struct at all. That absence is what makes it structurally different from [Remove channels from a device](#remove-channels-from-a-device): that function narrows a registration, this function erases it.

### Method(s)

```c
#include <pubnub/features/push.h>

pubnub_future_t pubnub_push_remove_device(pubnub_context_t* ctx,
                                           const pubnub_push_remove_device_opts_t* opts);
```

| Parameter | Description |
| --- | --- |
| `device` *Type: `const char*`Default: — | Borrowed, NUL-terminated. `NULL` or an empty string is rejected with `PUBNUB_ERR_INVALID_ARGUMENT`. |
| `gateway` *Type: `pubnub_push_gateway_t`Default: — | `PUBNUB_PUSH_APNS2` or `PUBNUB_PUSH_FCM`. |
| `topic`Type: `const char*`Default: — | Borrowed, NUL-terminated. |
| `environment`Type: `pubnub_push_environment_t`Default: `PUBNUB_PUSH_ENV_DEVELOPMENT` | Ignored for FCM. |
| `timeout_ms`Type: `uint32_t`Default: `0` (inherits `pubnub_config_t::transaction_timeout_ms`) | Per-call timeout override. |

Zero-initialize with `PUBNUB_PUSH_REMOVE_DEVICE_OPTS_INIT` (expands to `{0}`). The same [APNS2/FCM topic and environment rule](#add-channels-to-a-device) described above applies here unchanged.

**C-family contract**

* **Header** — `#include <pubnub/features/push.h>`
* **Types** — `pubnub_push_remove_device_opts_t`, `pubnub_push_gateway_t`, `pubnub_push_environment_t`
* **Prerequisite** — an initialized context
* **Feature flag** — `PUBNUB_ENABLE_PUSH_NOTIFICATIONS`
* **Ownership / lifetime** — `ctx` and `opts` are borrowed; `device` and `topic` are borrowed, caller-owned strings
* **Blocking** — never blocks; returns a `pubnub_future_t` immediately

### Sample code

```c
#include <pubnub/client.h>
#include <pubnub/features/push.h>
#include <pubnub/future.h>
#include <pubnub/response.h>

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    pubnub_config_t cfg = pubnub_config_defaults();
    cfg.subscribe_key = "demo";
    cfg.user_id       = "example-push-remove-device";

    pubnub_context_t* ctx = pubnub_create(&cfg);
    if (NULL == ctx) {
        return EXIT_FAILURE;
    }

    pubnub_future_t future =
        pubnub_push_remove_device(ctx,
                                   &(pubnub_push_remove_device_opts_t){
                                       .device  = "dXh7YzE:APA91bGExample",
                                       .gateway = PUBNUB_PUSH_FCM,
                                   });

    while (!pubnub_future_is_ready(future)) {
        pubnub_process(ctx);
    }

    if (PUBNUB_OK == pubnub_future_status(future)) {
        printf("Device removed from all push channels\n");
    }
    else {
        pubnub_string_view_t err = pubnub_response_error_message(future);
        fprintf(stderr, "Failed: %.*s\n", (int)err.len, err.ptr);
    }

    pubnub_future_release(future);
    pubnub_destroy(ctx);
    return 0;
}
```

### Returns

There is no result struct or payload accessor for this operation. Success is signaled entirely by the future's status: `pubnub_future_status(future) == PUBNUB_OK`.

## Error handling

`pubnub_res_t` is the single status type shared across every feature in this SDK, including Mobile Push. There are no per-feature error accessors. For the full result-code catalog and the `pubnub_response_service_error()` pattern for server-side error detail, see [Status Events](https://www.pubnub.com/docs/sdks/c/status-events.md).

Behaviors specific to the four functions on this page:

* `opts == NULL`, an invalid or uninitialized `ctx`, a `NULL`/empty `device`, or (on `pubnub_push_add_channels`/`pubnub_push_remove_channels`) a `NULL`/empty `channels` all fail immediately with `PUBNUB_ERR_INVALID_ARGUMENT`, readable via `pubnub_future_status()` without polling, awaiting, or sending any request.
* `gateway == PUBNUB_PUSH_APNS2` with `topic == NULL` fails the same way, on all four functions. See the [APNS2/FCM rule](#add-channels-to-a-device) above.
* On the wire, an HTTP status of `400` or higher maps to `PUBNUB_ERR_SERVER`, as does a `200` response whose body reports a logical failure. The exact wire shape that triggers this on a `200` response (for example, `add_channels`/`remove_channels`/`remove_device` probing the leading status digit of an array-shaped body) is an internal parsing detail, not a public contract, and could change without notice. Don't rely on it: call `pubnub_response_service_error()` for normalized detail regardless of which case produced it.

## Terms in this document

* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **Channel (DataSync)** - A built-in entity class in DataSync that stores channel metadata as a JSON payload. The same channel used for messaging and Presence.
* **Channel pattern** - A way to group and analyze channel data to track performance metrics like message counts and user engagement over time with PubNub Insights.
* **Push token** - A device identifier issued by a push provider (APNs or FCM) used to register a device for receiving mobile push notifications.

Last updated at: 2026-09-24T12:25:41.000Z
