Sending Messages

The globaliD messaging system is built around the notion of channels. A channel represents a place to send messages to; channels can be used to send messages privately between two identities:

     Identity 1                                 Identity 2
    +----------+            Channel            +----------+
    |          |      +-----------------+      |          |
    |          | -----|-----Message-----|----> |          |
    |          |      |                 |      |          |
    |          | <----|-----Message-----|----- |          |
    |          |      +-----------------+      |          |
    +----------+                               +----------+

Channels can also be used to support multi-person or "group" messaging:

     Identity 1                    Channel
    +----------+     +---------------------------------+
    |          | ----|-----message----+                |
    +----------+     |                |                | 
                     |                |                |
     Identity 2      |                |                |
    +----------+     |                |                |
    |          | <---|----------------+                |
    +----------+     |                |                |
                     |                |                |
     Identity 3      |                |                |
    +----------+     |                |                |
    |          | <---|----------------+                |
    +----------+     +---------------------------------+

Note that the term "group" here has nothing to do with globaliD Groups; group channels can be created completely independently of globaliD Groups.

If you wish to send a message to an identity, you should first see if there's already a channel for this conversation. To do this, you find the gid_uuid value for both yourself and the other person, and call the POST /v1/channels/search endpoint to find the matching channel if it exists, like this:

Request:

    POST /v1/channels/search
    BEARER <access_token>

    {
      "participants": ["gid_uuid1", "gid_uuid2"]
    }

Response:

    HTTP/1.1 200 OK

    {
      "data": [
        {
          "id": "...",
          "uuid": "...",
          "type": "...",
          "exposed": false,
          ...
        }
      ],
      "meta": {
        "page": 1,
        "per_page": 50,
        "total": 1
      }
    }

If there is already a channel for communicating with the given identity, the data array will have a single entry which holds the details of the channel to use. Otherwise, the data array will be empty.

If the desired channel does not already exist, you can create it by calling the POST /v1/channels endpoint:

Request:

   POST /v1/channels
   BEARER <access_token>

   {
      "participants": ["gid_uuid1", "gid_uuid2"]
      "exposed": false,
      "type": "PERSONAL"
   }

Response:

   HTTP/1.1 201 CREATED

   {
     "id": "...",
     "type": "PERSONAL",
     "exposed": false,
     "participants": [...],
     "unread_count": 0,
     ...
   }

For private identity-to-identity channels, exposed should be set to false and type should be set to 'PERSONAL'.

id is the unique ID number for this channel. Once you have the channel ID, you can send a message to the channel by calling the POST /v1/messages endpoint:

Request:

   POST /v1/messages
   BEARER <access_token>

   {
     "message": {
       "type": "text",
       "content": {
         "text": "<text of message>"
       }
     },
     "recipients: {
       "channels": [<channel_id>]
     }
   }

Response:

   HTTP/1.1 201 CREATED

   {
     "id": <message_id>,
     "sequence_id": <message_sequence_id>,
     "type": "text",
     "author": "...",
     "channel_id": <channel_id>,
     "content": { ... },
     "delivered": false,
     "deleted": false,
     "created_at": "...",
     "updated_at": "..."
   }

As you can see, a copy of the newly-generated message is returned. Each message has an id value which uniquely identifies this message. The other fields are as follows:

  • sequence_id: the sequence number of the message within the channel. This can be used to retrieve all messages in a channel in the order in which they were sent.
  • type: the type of message, in this example a plain-text message.
  • author: the gid_uuid value for the sender of the message.
  • channel_id: the ID of the channel where this message was sent.
  • content: the contents of the message. For simple text messages, the content object will have a text field containing the message that was sent.
  • delivered: has this message been delivered?
  • seen: has this message been seen by the recipient?
  • deleted: has this message been deleted?
  • created_at: the date and time at which this message was created, in ISO-8601 format.
  • updated_at: the date and time at which this message was last updated, in ISO-8601 format.

Receiving Messages

There are two ways in which messages can be received: by polling the channel, or by using the real-time message transport layer. In general, you should only poll the channel if your app has been offline and you need to retrieve all messages received while the app was offline. While the app is running, you should use the real-time transport system to receive messages automatically in real time.

To retrieve all the messages sent to a channel, you can use the GET /v1/channels/<channel_id>/messages endpoint:

Request:

   GET /v1/channels/<channel_id>/messages
   BEARER <access_token>

Response:

   HTTP/1.1 200 OK

   {
     "data": {
       "messages": [
         {
           "id": <message_id>,
           "sequence_id": <message_sequence_id>,
           "type": "text",
           "author": "...",
           "channel_id": <channel_id>,
           "content": { ... },
           "delivered": false,
           "seen": false,
           "deleted": false,
           "created_at": "...",
           "updated_at": "..."
         },
         ...
       ]
     },
     "meta": {
       "page": 1,
       "per_page": 50,
       "total": 236
     }
   }

The returned messages array holds a number of messages which were sent to the channel, while the meta object holds information about the pagination of the returned messages. You can use the per_page query-string parameter to change the number of messages which are returned at once, and the page query-string parameter to return additional pages of messages. For example:

`GET /v1/channels/1/messages?per_page=100&page=1`
`GET /v1/channels/1/messages?per_page=100&page=2`
`GET /v1/channels/1/messages?per_page=100&page=3`
`GET /v1/channels/1/messages?per_page=100&page=4`

In this way, you can download all of the messages which were sent to a given channel.

Because each message has a sequence_id value, it is possible to cache the messages and only download any messages sent to the channel since the last time you checked. For example, if the most recently downloaded message had a sequence_id of 1234, you could call the following endpoint to retrieve any new messages which have been sent to the channel in since message 1234 was sent:

`GET /v1/channels/1/messages?from_sequence_id=1234`

Marking a Message as Delivered

When your app receives a new message, it should call the PUT /v1/messages/<message_id>/delivered API endpoint to tell the messaging system that the message has been delivered:

Request:

   PUT /v1/messages/<message_id>/delivered
   BEARER <access_token>

Response:

   HTTP/1.1 200 OK

   {
     "id": <message_id>,
     ...
   }

To see if a message you sent has been delivered, you can call the GET /v1/messages/:message_id endpoint:

Request:

   GET /v1/messages/<message_id>
   BEARER <access_token>

Response:

   HTTP/1.1 200 OK

   {
     "id": "...",
     "delivered": false,
     ...
   }

The delivered field will be set to true when the message has been delivered.

Marking a Message as Seen

When the user views a new person-to-person message for the first time, your app should call the PUT /v1/messages/<message_id>/seen endpoint to tell the messaging system that the recipient has seen the message:

Request:

   PUT /v1/messages/<message_id>/seen
   BEARER <access_token>

Response:

   HTTP/1.1 200 OK

   {
     "id": <message_id>,
     ...
   }

To see if a message you sent has been seen by the recipient, you can call the GET /v1/messages/:message_id endpoint:

Request:

   GET /v1/messages/<message_id>
   BEARER <access_token>

Response:

   HTTP/1.1 200 OK

   {
     "id": "...",
     "seen": false,
     ...
   }

The seen field will be set to true when the message has been seen by the recipient.

Real-time Delivery

The globaliD system uses PubNub to provide real-time delivery of messages and notifications.

More to come...