Please be aware that you are viewing our bleeding edge unstable documentation. Unless you wanted to view the bleeding edge (and possibly unstable) documentation, we recommend you use our stable docs.

Go to Ably's stable canonical documentation »

I know what I'm doing, let me see the bleeding edge docs »

You are viewing our bleeding edge unstable documentation. We recommend you use our stable documentation »
Fork me on GitHub

REST API Beta Features

REST API Beta Features

The contents of this section are beta features of our REST API. Although many of these features are fully functional, until the feature is released as generally available, the APIs may change. We recommend customers get in touch if they want to use these features in production.

Batch requests

Batch mode is a way of querying an API multiple times with a single HTTP request. The simplest example to consider is publishing a single message to multiple channels; a single request is made, indicating the channels and the contents of the message, and the system attempts to publish on all channels in parallel. Each of those attempts may succeed or fail independently. The batch mode API provides a way for the results of that request to be indicated back to the caller.

Generic operation

A batch mode request translates a single set of request details (ie the request body, params and headers) in to an array of requests for the underlying API. Each of those requests is then performed in parallel.

Once each request has completed, the batch-mode response is formulated to be returned to the caller. There are three possible outcomes:

All batch-mode api calls are limited to addressing at most 100 different channels per request.

Bulk publish

The REST API has been extended to include batch-mode publish operations. The API concerned is:

POST /messages

This is the new bulk publish API which is implicitly a batch-mode API. This performs a publish in parallel of messages to channels specified in the request body. Check out the code example below on how to do this with the request method in the REST client library.

var ablyRest = new Ably.Rest({ key: '{{API_KEY}}' })
var content = { "channels": [ "test1", "test2" ], "messages": { "data": 'myData' } }
ablyRest.request('post', '/messages', null, content, null,
function(err, response) {
  if(err) {
    alert('An error occurred; err = ' + err.toString());
  } else {
    alert('Success! status code was ' + response.statusCode);
  }
});

You can also use the REST API directly with the following:

curl -X POST https://rest.ably.io/messages \
    -u "{{API_KEY}}" \
    -H "Content-Type: application/json" \
    --data '{ "channels": [ "test1", "test2"],
"messages": {"data": "My test message text" } }'

A single BatchSpec is an object of the form:

{
  channels: <channel names>,
  messages: <messages>
}

where:

The bulk publish endpoint accepts a request body containing either a single BatchSpec object, or an array of BatchSpec objects.

Therefore the following are all valid request bodies for a bulk publish request:

Using a single BatchSpec object
{
  channels: ['a channel name, containing a comma', 'another channel name'],
  messages: {data: 'My message contents'}
}
Using multiple BatchSpec objects in an array
[
  {
    channels: ['a channel name, containing a comma', 'another channel name'],
    messages: {data: 'My message contents'}
  },
  {
    channels: 'single channel',
    messages: [
      {data: 'My message contents'},
      {name: 'an event', data: 'My event message contents'},
    ]
  }
]

There is an obvious mapping from the request body to the array of individual publish requests.

The 100 channel limit caps the total number of different channels in the request, irrespective of how they are arranged. So if the same channel name occurs in multiple BatchSpec objects in a single requests, it will contribute only one channel towards the limit.

Batch reponses

The request

POST /messages
{
  channels: ['channel0', 'channel1', 'channel2'],
  messages: {data: 'My test message text'}
}

would have the following possible outcomes:

Success:

status code: 201
response body:
[
  {
    "channel":"channel0",
    "messageId":"w234r5t-fr5"
  },
  {
    "channel":"channel1",
    "messageId":"vde4sfc0p"
  },
  {
    "channel":"channel2",
    "messageId":"nh3exv8ih"
  }
]

Common-cause failure:

status code: 401
response body:
{
  "error": {
    "message":"Token expired",
    "statusCode":401,
    "code":40140
  }
}

Partial success:

status code: 400
response body
{
  "error": {
    "message": "Batched response includes errors",
    "statusCode":400,
    "code":40020
  }
  "batchResponse": [
    {
      "channel":"channel0",
      "messageId":"w234r5t-fr5"
    },
    {
      "channel":"channel1",
      "messageId":"vde4sfc0p"
    },
    {
      "channel":"channel2",
      "error": {
        "message": "Given credentials do not have the required capability",
        "statusCode": 401,
        "code": 40160
      }
    }
  ]
}

Batch presence

The REST API has been extended to include batch-mode presence operations. The API concerned is:

GET /presence

This an API to retrieve the presence state of multiple channels and is a batch-mode API. This performs a presence get in parallel on a set of channels specified in the request params. Check out the code example below on how to do this with the request method in the REST client library.

var ablyRest = new Ably.Rest({ key: '{{API_KEY}}' })
var content = { "channel": <channel names> }
ablyRest.request('GET', '/presence', content, null, {}, function(err, response) {
  if(err) {
    alert('An error occurred; err = ' + err.toString());
  } else {
    alert('Success! status code was ' + response.statusCode);
  }
});

You can also use the REST API directly with the following:

curl -X GET https://rest.ably.io/presence?channel=<channel names> \
    -u "{{API_KEY}}"

where:

Below is an example of a curl request which uses a separator to separate channels channel,1 and channel,2:

curl -X GET https://rest.ably.io/presence?channel,1!channel,2=&separator=! \
    -u "{{API_KEY}}"

Batch responses

The request:

GET /presence
{
  channel: 'channel0,channel1,channel2'
}

would have the following possible outcomes:

Success:

status code: 200
response body:
[
  {
    "channel":"channel0",
    "presence":[
      {"clientId": "user1", "action": "1"},
      {"clientId": "user2", "action": "1"}
    ]
  },
  {
    "channel":"channel1",
    "presence":[]
  },
  {
    "channel":"channel2",
    "presence":[
      {"clientId": "user2", "action": "1"},
      {"clientId": "user3", "action": "1"}
    ]
  }
]

Common-cause failure:

status code: 401
response body:
{
  "error": {
    "message":"Token expired",
    "statusCode":401,
    "code":40140
  }
}

Partial success:

status code: 400
response body
{
  "error": {
    "message": "Batched response includes errors",
    "statusCode":400,
    "code":40020
  }
  "batchResponse": [
    {
      "channel":"channel0",
      "presence":[
        {"clientId": "user1", "action": "1"},
        {"clientId": "user2", "action": "1"}
      ]
    },
    {
      "channel":"channel1",
      "presence":[]
    },
    {
      "channel":"channel2",
      "error": {
        "message": "Given credentials do not have the required capability",
        "statusCode": 401,
        "code": 40160
      }
    }
  ]
}

Batch responses with the request method

When using the request method in a library, you’ll need to handle the potential responses for success, partial success, and failure.

For a response object response, response.success will be true if the batch presence was successful, or false if at least one presence request failed. response.statusCode will be 200 for complete success, 400 for partial success, and 401 for an expected failure. response.errorCode will contain the Ably error code, and response.errorMessage will contain details of the error.

For successful requests, response.items will contain a list of the responses for each individual channel from which presence has been requested.

For partially successful requests, response.items.batchResponse will contain a list of the individual channel’s results, be it an error or a success. You will know a partial success has occurred by the response.errorCode, which will be 40020.

Below would be an example of how to deal with these:

var ablyRest = new Ably.Rest({ key: '{{API_KEY}}' })
var content = { "channel": "channel1,channel2" }
ablyRest.request('GET', '/presence', content, null, {}, function(err, response) {
  if(err) {
    // Throw error
  } else {
    if(response.success) {
      // If complete success
      for(i = 0; i < response.items.length; i++) {
        // Each response item will be roughly of the style:
        /*
          {
            "channel": "channel1",
            "presence": [
              { "action": 1, "clientId": "CLIENT1" },
              { "action": 1, "clientId": "CLIENT2" }
            ]
          }
        */
      }
    } else if(response.errorCode === 40020) {
      // If partial success
      for(i = 0; i < response.items[0].batchResponse.length; i++) {
        // Each batchResponse item will either be the same as success if it succeeded, or:
        /*
          {
            "channel": "channel1",
            "error": {
              "code": 40160,
              "message": "ERROR_MESSAGE",
              "statusCode": 401
            }
          }
        */
      }
    } else {
      // If failed, check why
      console.log(response.errorCode + ', ' + response.errorMessage);
    }
  }
});

Back to top