REST Client Library API

Messages

Ably DSN allows for clients to send information with messages, which contain data the client wishes to communicate. These messages are published through channels, which other users can subscribe to in order to receive them. 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.osNqDA:gNhazskHAN_BY5gG');
var channel = rest.channels.get('old-hen-bot');
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.osNqDA:gNhazskHAN_BY5gG');
var channel = rest.channels.get('old-hen-bot');
channel.publish('example', 'message data', function() {
  channel.history(function(err, resultPage) {
    console.log('Last published message:' + resultPage.items[0]);
  });
});
rest = Ably::Rest.new('xVLyHw.osNqDA:gNhazskHAN_BY5gG')
channel = rest.channels.get('old-hen-bot')
channel.publish 'example', 'message data'
result_page = channel.history()
puts "Last published message: #{result_page.items.first}"
rest = AblyRest('xVLyHw.osNqDA:gNhazskHAN_BY5gG')
channel = rest.channels.get('old-hen-bot')
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.osNqDA:gNhazskHAN_BY5gG');
$channel = $rest->channels->get('old-hen-bot');
$channel->publish('example', 'message data');
$resultPage = $channel->history();
echo("Last published data: " . $resultPage->items[0]->data);
AblyRest rest = new AblyRest("xVLyHw.osNqDA:gNhazskHAN_BY5gG");
Channel channel = rest.channels.get("old-hen-bot");
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.osNqDA:gNhazskHAN_BY5gG");
var channel = rest.Channels.Get("old-hen-bot");
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.osNqDA:gNhazskHAN_BY5gG"];
ARTRestChannel *channel = [rest.channels get:@"old-hen-bot"];
[channel publish:@"example" data:@"message data"];
[channel history:^(ARTPaginatedResult<ARTMessage *> *resultPage, ARTErrorInfo *error) {
    NSLog(@"Last published message ID: %@", resultPage.items[0].id);
}];
rest, err := ably.NewRestClient(ably.NewClientOptions("xVLyHw.osNqDA:gNhazskHAN_BY5gG"))
channel := rest.Channels.Get("old-hen-bot", nil)
err = channel.Publish("example", "message data")
page, err := channel.History(nil)
fmt.Println("Last published message: %s\n", page.Messages[0].Data)

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

Messages

Each message published has an optional event name propertymemberattribute and a data propertymemberattribute carrying the payload of the message. Various primitive and object types are defined, portable and supported in all clients, enabling clients to be interoperable despite being hosted in different languages or environments.

The supported payload types are Strings, JSON objects and arrays, plain c# objects which are converted to json, buffers containing arbitrary binary data, and Null objects. Client libraries detect the supplied message payload and encode the message appropriately.

Subscribing to messages

The REST client library does not offer message realtime subscription but instead provides access to the “live” history using the REST history API. Find out more about subscribing to messages in realtime using the Realtime API.

The name propertymemberattribute of published messages does not affect the distribution of a channel message to clients but may be used as a subscription filter, allowing a client to register a listener that only sees a subset of the messages received on the channel. Find out more about registering listeners using the Realtime API.

Publishing messages

Channels expose a publish method whereby a client can publish either a single message or an array of messages to a channel over REST.

channel.publish('event', 'This is my payload', function(err) {
  if(err) {
    console.log('Unable to publish message; err = ' + err.message);
  } else {
    console.log('Message successfully sent');
  }
});
channel.publish('event', 'This is my payload', function(err) {
  if(err) {
    console.log('Unable to publish message; err = ' + err.message);
  } else {
    console.log('Message successfully sent');
  }
});
channel.publish('event', 'This is my payload')
channel.publish(u'event', u'This is my payload')
$channel->publish('event', 'This is my payload');
channel.publish("event", "This is my payload");
channel.PublishAsync("event", "This is my payload");
[channel publish:@"event" data:@"This is my payload"];
channel.publish("event", data: "This is my payload")
channel.Publish("event", "This is my payload")

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. With a realtime connection, you can also effectively send a message to multiple channels at once by allowing multiple concurrent publish operations.

Enabling idempotent publishing

Idempotency ensures that multiple publishes of the same message cannot result in duplicate messages. Find out more about what idempotency is, and how we provide idempotency in our REST operations.

It is possible for a client publishing through REST to not receive an acknowledgement of receipt from Ably for numerous reasons such as network failures outside of our control. This can lead to the client automatically re-publishing the message, which is a feature of our SDKs to help route around network failures. We recommend that you enable idempotent publishing in our REST SDKs if you want to avoid these retry attempts potentially resulting in duplicate messages. When enabled, the REST SDK automatically assigns a unique ID to each message ensuring subsequent retries cannot result in duplicates.

If you provide a unique ID with each message published, all publishes will be idempotent – that is you can freely publish the message from one or more workers without worrying about duplicates. Please note that publishing multiple messages in a single publish operation with client-specified ids has many constraints you need to be aware of.

Below is an example of how to provide a unique ID:

var rest = new Ably.Rest('xVLyHw.osNqDA:gNhazskHAN_BY5gG');
var channel = rest.channels.get('old-hen-bot');
channel.publish([{data: 'payload', id: 'unique123'}]);

Publishing on behalf of realtime connection

Message published using the REST API may be done so on behalf of an existing realtime connection when a valid connectionKey is present in the published message. For example, if you want to publish a message using the REST client library so that it appears to come from an existing connected realtime client, then the connection’s private (secret) connection key must be included. See a publish on behalf of a realtime client example.

If the connectionKey is invalid or belongs to a connection that has since been closed, then the publish operation will fail.

Retrieving message history

Channels expose a historyHistory method providing a means for clients to obtain messages previously sent on the channel. Channel history can be used to return continuous message history up to the exact point a realtime channel was attached.

History provides access to instantaneous “live” history as well as the longer term persisted history for attached channels. If persisted history is enabled for the channel, then messages will typically be stored for 24 – 72 hours. If persisted history is not enabled, Ably retains the last two minutes of message history in memory.

The following example retrieves the first two pages of historical messages published up until the point the channel was attached.

channel.history(function(err, resultPage) {
  if(err) {
    console.log('Unable to get channel history; err = ' + err.message);
  } else {
    console.log(resultPage.items.length + ' messages received in first page');
    if(resultPage.hasNext()) {
      resultPage.next(function(err, nextPage) { ... });
    }
  }
});
channel.history(function(err, resultPage) {
  if(err) {
    console.log('Unable to get channel history; err = ' + err.message);
  } else {
    console.log(resultPage.items.length + ' messages received in first page');
    if(resultPage.hasNext()) {
      resultPage.next(function(err, nextPage) { ... });
    }
  }
});
PaginatedResult<Message> resultPage = channel.history(null);
System.out.println(resultPage.items().length + " messages received in first page");
if(resultPage.hasNext()) {
  PaginatedResult<Message> nextPage = resultPage.next();
  System.out.println(nextPage.items().length + " messages received in second page");
}
PaginatedResult<Message> resultPage = await channel.HistoryAsync();
Console.WriteLine(resultPage.Items.Count + " messages received in first page");
if(resultPage.HasNext) {
  PaginatedResult<Message> nextPage = await resultPage.NextAsync();
  Console.WriteLine(nextPage.Items.Count + " messages received in second page");
}
result_page = channel.history
puts "#{result_page.items.length} messages received in first page"
if result_page.has_next?
  next_page = result_page.next
  puts "#{next_page.items.length} messages received in second page"
end
result_page = channel.history()
print str(len(result_page.items)) + ' messages received in first page'
if result_page.has_next():
  next_page = result_page.next()
  print str(len(next_page.items)) + ' messages received in second page'
$resultPage = channel->history();
echo(count($resultPage->items) . 'messages received in first page');
if($resultPage->hasNext()) {
  $nextPage = $resultPage.next();
  echo(count($resultPage->items) . 'messages received in second page');
}
[channel history:^(ARTPaginatedResult<ARTMessage *> *resultPage, ARTErrorInfo *error) {
  NSLog(@"%lu messages received in first page", (unsigned long)[resultPage.items count]);
  if (resultPage.hasNext) {
    [resultPage next:^(ARTPaginatedResult<ARTMessage *> *nextPage, ARTErrorInfo *error) {
      // ...
    }];
  }
}];
channel.history { resultPage, error in
  let resultPage = resultPage!
  print("\(resultPage.items.count) messages received in first page")
  if resultPage.hasNext {
    resultPage.next { nextPage, error in
      // ...
    }
  }
}
page, err := channel.History(nil)
fmt.Println("%d messages received in first page\n", len(page.Messages()))
if page.hasNext() {
  page2, err := page.Next()
  //...
}

See the history documentation for further details of the supported query parameters.

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.

Message API Reference

PropertiesMembersAttributesAttributes

A Message represents an individual message that is sent to or received from Ably.

nameName

The event name, if provided.
Type: String

dataData

The message payload, if provided.
Type: String, StringBuffer, JSON ObjectString, ByteArray, JSONObject, JSONArrayString, byte[], plain C# object that can be serialized to JsonString, Binary (ASCII-8BIT String), Hash, ArrayString, Bytearray, Dict, ListString, Binary String, Associative Array, ArrayNSString *, NSData *, NSDictionary *, NSArray *String, NSData, Dictionary, Array

extrasExtras

Metadata and/or ancillary payloads, if provided. The only currently valid payload for extras is the push object.
Type: JSONObject, JSONArrayplain C# object that can be converted to JsonJSON ObjectHash, ArrayDict, ListDictionary, ArrayNSDictionary *, NSArray *Associative Array, Array

idId

A Unique ID assigned by Ably to this message. Can optionally be assigned by the client as part of idempotent publishing.
Type: String

clientIdClientIdclient_idclient_id

The client ID of the publisher of this message.
Type: String

connectionIdConnectionIdconnection_idconnection_id

The connection ID of the publisher of this message.
Type: String

timestampTimestamp

Timestamp when the message was received by the Ably, as milliseconds since the epocha Time object
.Type: IntegerLong IntegerDateTimeOffsetTimeNSDate

encodingEncoding

This will typically be empty as all messages received from Ably are automatically decoded client-side using this value. However, if the message encoding cannot be processed, this attribute will contain the remaining transformations not applied to the data payload.
Type: String

Message methods

Message.fromEncoded

Message.fromEncoded(Object encodedMsg, ChannelOptions channelOptions?) → Message

A static factory method to create a Message from a deserialized Message-like object encoded using Ably’s wire protocol.

Parameters

encodedMsg
a Message-like deserialized object.
Type: Object
channelOptions
an optional ChannelOptions. If you have an encrypted channel, use this to allow the library can decrypt the data.
Type: Object

Returns

A Message object

Message.fromEncodedArray

Message.fromEncodedArray(Object[] encodedMsgs, ChannelOptions channelOptions?) → Message[]

A static factory method to create an array of Messages from an array of deserialized Message-like object encoded using Ably’s wire protocol.

Parameters

encodedMsgs
an array of Message-like deserialized objects.
Type: Array
channelOptions
an optional ChannelOptions. If you have an encrypted channel, use this to allow the library can decrypt the data.
Type: Object

Returns

An Array of Message objects


API reference
Documentation

Ready to get started?

Our free plan includes 3m messages per month, 100 peak connections, 100 peak channels, and loads of features.