REST Client Library API

Channels

Ably Platform organizes the message traffic within applications into named channels. Channels are the medium through which messages are distributed; clients attach to channels to subscribe to messages, and every message published to a unique channel is broadcast by Ably to all subscribers. This scalable and resilient messaging pattern is commonly called pub/sub.

Getting started

The Ably REST client library provides a straightforward API for publishing messages and retrieving message history from a channel.

var rest = new Ably.Rest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
var channel = rest.channels.get('box-big-jam');
channel.publish('example', 'message data', function() {
  channel.history(function(err, resultPage) {
    console.log('Last published message:' + resultPage.items[0]);
  });
});
var rest = new Ably.Rest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
var channel = rest.channels.get('box-big-jam');
channel.publish('example', 'message data', function() {
  channel.history(function(err, resultPage) {
    console.log('Last published message:' + resultPage.items[0]);
  });
});
rest = Ably::Rest.new('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M')
channel = rest.channels.get('box-big-jam')
channel.publish 'example', 'message data'
result_page = channel.history()
puts "Last published message: #{result_page.items.first}"
rest = AblyRest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M')
channel = rest.channels.get('box-big-jam')
channel.publish(u'example', u'message data')
result_page = channel.history()
print("Last published message data: " + result_page.items[0].data)
$rest = new Ably\AblyRest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
$channel = $rest->channels->get('box-big-jam');
$channel->publish('example', 'message data');
$resultPage = $channel->history();
echo("Last published data: " . $resultPage->items[0]->data);
AblyRest rest = new AblyRest("xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M");
Channel channel = rest.channels.get("box-big-jam");
channel.publish("example", "message data");
PaginatedResult<Message> resultPage = channel.history(null);
System.out.println("Last published message ID: " + resultPage.items[0].id);
AblyRest rest = new AblyRest("xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M");
var channel = rest.Channels.Get("box-big-jam");
await channel.PublishAsync("example", "message data");
PaginatedResult<Message> resultPage = await channel.HistoryAsync();
Console.WriteLine("Last published message ID: " + resultPage.Items[0].id);
ARTRest *rest = [[ARTRest alloc] initWithKey:@"xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M"];
ARTRestChannel *channel = [rest.channels get:@"box-big-jam"];
[channel publish:@"example" data:@"message data"];
[channel history:^(ARTPaginatedResult<ARTMessage *> *resultPage, ARTErrorInfo *error) {
    NSLog(@"Last published message ID: %@", resultPage.items[0].id);
}];
let rest = ARTRest(key: "xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M")
let channel = rest.channels.get("box-big-jam")
channel.publish("example", data: "message data")
channel.history { resultPage, error in
    print("Last published message ID: \(resultPage!.items[0].id)")
}
rest, err := ably.NewREST(ably.WithKey("xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M"))
if err != nil {
    panic(err)
}
channel := rest.Channels.Get("box-big-jam")
if err := channel.Publish(ctx, "example", "message data"); err != nil {
    panic(err)
}
pages, err := channel.History().Pages(context.Background())
if err != nil {
    panic(err)
}
for pages.Next(context.Background()) {
    for _, message := range pages.Items() {
        fmt.Println(jsonify(message))
        fmt.Println("--------")
    }
}
if err := pages.Err(); err != nil {
    panic(err)
}
final rest = ably.Rest(key: 'xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
final channel = rest.channels.get('box-big-jam');
await channel.publish(name: 'example', data: 'message data');
PaginatedResult<Message> resultPage = channel.history();
print('Last published message ID: ${resultPage.items[0].id}');

If you would prefer to just dive into code and see some examples of how to use channels, then we recommend you take a look at our REST tutorials.

It is also possible to publish a message to multiple channels at once using our batch publish feature.

Channels

In order to publish, retrieve message history or access presence history, you must first obtain a REST channel instance.

Obtaining a channel instance

A Channel object is a reference to a single channel. A channel instance is obtained from the channels collection of the Rest::ClientAblyRestRest instance, and is uniquely identified by its unicode string name. You can only connect to one channel in a single operation, so wildcards are not supported. Find out more about channel naming

var channel = rest.channels.get('channelName');
var channel = rest.channels.get('channelName');
Channel channel = rest.channels.get("channelName");
Channel channel = rest.Channels.Get("channelName");
channel = rest.channels.get('channelName')
channel = rest.channels.get('channelName')
$channel = $rest->channels->get('channelName');
ARTRestChannel *channel = [realtime.channels get:@"channelName"];
let channel = realtime.channels.get("channelName")
channel := rest.Channels.Get("channelName")
final channel = rest.channels.get('channelName');

To find out more about subscribing to messages published on channels in realtime, see the Realtime channel API.

Setting channel options and encryption

A set of channel options may also be passed to configure a channel for encryption. Find out more about symmetric message encryption.

Crypto.generateRandomKey(function(err, key) {
  var options = { cipher: { key: key } };
  var channel = rest.channels.get('channelName', options);
});
Crypto.generateRandomKey(function(err, key) {
  var options = { cipher: { key: key } };
  var channel = rest.channels.get('channelName', options);
});
CipherParams params = Crypto.getDefaultParams(key);
ChannelOptions options = new ChannelOptions();
options.encrypted = true;
options.cipherParams = params;
Channel channel = rest.channels.get("channelName", options);
CipherParams cipherParams = Crypto.GetDefaultParams(key);
var options = new ChannelOptions(cipherParams);
var encryptedChannel = rest.Channels.Get("channelName", options);
key = Ably::Util::Crypto.generate_random_key
options = { cipher: { key: key } }
channel = rest.channels.get('channelName', options)
key = ably.util.crypto.generate_random_key()
channel = rest.channels.get('channelName', cipher={'key': key})
$key = Ably\Crypto->generate_random_key();
$options = array('cipher' => array('key' => key));
$channel = $rest->channels->get('channelName', $options);
NSData *key = [ARTCrypto generateRandomKey];
ARTChannelOptions *options = [[ARTChannelOptions alloc] initWithCipherKey:key];
ARTRestChannel *channel = [rest.channels get:@"channelName" options:options];
let key = ARTCrypto.generateRandomKey()
let options = ARTChannelOptions(cipherKey: key)
let channel = rest.channels.get("channelName", options: options)
cipher := ably.CipherParams{
       Key:       key,
       KeyLength: 128,
       Algorithm: ably.CipherAES,
    }
channel := rest.Channels.Get("channelName", ably.ChannelWithCipher(cipher))

Publishing to a channel

To publish to a channel, make use of the publish method of the channel:

var rest = new Ably.Rest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
var channel = rest.channels.get('box-big-jam');
channel.publish('example', 'message data');
var rest = new Ably.Rest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
var channel = rest.channels.get('box-big-jam');
channel.publish('example', 'message data');
rest = Ably::Rest.new('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M')
channel = rest.channels.get('box-big-jam')
channel.publish 'example', 'message data'
rest = AblyRest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M')
channel = rest.channels.get('box-big-jam')
channel.publish(u'example', u'message data')
$rest = new Ably\AblyRest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
$channel = $rest->channels->get('box-big-jam');
$channel->publish('example', 'message data');
AblyRest rest = new AblyRest("xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M");
Channel channel = rest.channels.get("box-big-jam");
channel.publish("example", "message data");
AblyRest rest = new AblyRest("xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M");
var channel = rest.Channels.Get("box-big-jam");
await channel.PublishAsync("example", "message data");
ARTRest *rest = [[ARTRest alloc] initWithKey:@"xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M"];
ARTRestChannel *channel = [rest.channels get:@"box-big-jam"];
[channel publish:@"example" data:@"message data"];
let rest = ARTRest(key: "xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M")
let channel = rest.channels.get("box-big-jam")
channel.publish("example", data: "message data")
rest, err := ably.NewREST(ably.WithKey("xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M"))
if err != nil {
    panic(err)
}
channel := rest.Channels.Get("box-big-jam")
if err := channel.Publish(ctx, "example", "message data"); err != nil {
    panic(err)
}
final rest = ably.Rest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
final channel = rest.channels.get('box-big-jam');
channel.publish(name: 'example', data: 'message data');

Getting history of a channel

To get the history of a channel, make use of the history method of the channel:

var rest = new Ably.Rest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
var channel = rest.channels.get('box-big-jam');
channel.history(function(err, resultPage) {
  console.log('Last published message:' + resultPage.items[0]);
});
var rest = new Ably.Rest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
var channel = rest.channels.get('box-big-jam');
channel.history(function(err, resultPage) {
  console.log('Last published message:' + resultPage.items[0]);
});
rest = Ably::Rest.new('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M')
channel = rest.channels.get('box-big-jam')
result_page = channel.history()
puts "Last published message: #{result_page.items.first}"
rest = AblyRest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M')
channel = rest.channels.get('box-big-jam')
result_page = channel.history()
print("Last published message data: " + result_page.items[0].data)
$rest = new Ably\AblyRest('xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M');
$channel = $rest->channels->get('box-big-jam');
$resultPage = $channel->history();
echo("Last published data: " . $resultPage->items[0]->data);
AblyRest rest = new AblyRest("xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M");
Channel channel = rest.channels.get("box-big-jam");
PaginatedResult<Message> resultPage = channel.history(null);
System.out.println("Last published message ID: " + resultPage.items[0].id);
AblyRest rest = new AblyRest("xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M");
var channel = rest.Channels.Get("box-big-jam");
PaginatedResult<Message> resultPage = await channel.HistoryAsync();
Console.WriteLine("Last published message ID: " + resultPage.Items[0].id);
ARTRest *rest = [[ARTRest alloc] initWithKey:@"xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M"];
ARTRestChannel *channel = [rest.channels get:@"box-big-jam"];
[channel history:^(ARTPaginatedResult<ARTMessage *> *resultPage, ARTErrorInfo *error) {
    NSLog(@"Last published message ID: %@", resultPage.items[0].id);
}];
let rest = ARTRest(key: "xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M")
let channel = rest.channels.get("box-big-jam")
channel.history { resultPage, error in
    print("Last published message ID: \(resultPage!.items[0].id)")
}
rest, err := ably.NewREST(ably.WithKey("xVLyHw.zJgRZA:hRcQ9W2-_2aCQRmS-9FKlzg7pASmIh2oPaVe8oXOE6M"))
if err != nil {
    panic(err)
}
channel := rest.Channels.Get("box-big-jam")
pages, err := channel.History().Pages(context.Background())
if err != nil {
   panic(err)
}
for pages.Next(context.Background()) {
   for _, message := range pages.Items() {
       fmt.Println(jsonify(message))
       fmt.Println("--------")
   }
}
if err := pages.Err(); err != nil {
   panic(err)
}

Batch publishing

It is common for a single message to be intended for multiple channels. If you wish to send a message to multiple channels within a single operation, you can make use of the REST batch API.

Channel metadata

Ably provides a REST API to query your app for metadata about channels, as well as a realtime API to subscribe to channel lifecycle events. Using the REST API, you can enumerate all active channels, or obtain the status of an individual channel. Using our Realtime API, you can subscribe to channel lifecycle events (such as being created or closed etc), or subscribe to periodic occupancy updates for all active channels (such as how many people are subscribed to a channel).

Channel namespaces

One or more channel rules may be configured for an app in your dashboard. These are rules which apply to a channel based on its ‘namespace’. The namespace is the first colon-delimited segment of its name (from the start, up to and including, the last character before the :). If the channel name contains no colon, the namespace is the entire channel name.

For example, the following channels are all part of the “public” namespace:

  • public
  • public:events
  • public:news:americas

Note that wildcards are not supported in channel namespaces.

The namespace attributes that can be configured are:

  • Persist all messages – if enabled, all messages within this namespace will be stored according to the storage rules for your account (24 hours for free accounts). You can access stored messages via the history API . Please note that for each message stored, an additional message is deducted from your monthly allocation.
  • State persistence – if enabled, the very last message published on a channel will be stored for an entire year, retrievable using the channel rewind mechanism by attaching to the channel with rewind=1. Only messages are stored, not presence messages. This last message storage is not accessible using the normal history API, only through rewind.
  • Identified – if enabled, clients will not be permitted to use (including to attach, publish, or subscribe) matching channels unless they are identified (they have an assigned client ID). Anonymous clients are not permitted to join these channels. Find out more about authenticated and identified clients
  • TLS only – if enabled, only clients who have connected to Ably over TLS will be allowed to use matching channels. Find out more
  • Push notifications enabled – If checked, publishing messages with a push payload in the extras field is permitted and can trigger the delivery of a push notification to registered devices for the channel. Find out more.

Key or token capabilities can also specify access rights based on channel namespace. Find out more about authentication.

Presence

Channels expose a presencePresence member which a client can use to obtain present members and presence event history for the channel itself. See the REST presence documentation for details.

API Reference

View the Channels and Channel API Reference.


Need help?

If you need any help with your implementation or if you have encountered any problems, do get in touch. You can also quickly find answers from our knowledge base, and blog.