Presence

You can use presence to mark users as available/offline/busy/away and display that information to their followers. Presence can only be used if there is a persistent WebSocket connection established. Information is modeled as transient properties that are added to the Identity object.

Name Type Description
presence Presence Object An object modeling presence state for the identity.
presence.status String A string value of “available”, “busy”, “away”, or “offline” for other users. Also includes “invisible” for the authenticated user’s status and “auto” for automatically restoring the last status.
presence.last_seen_at Date The time the user last set a status. null if the user has never set a status.

Connection

All presence state is tied to the currently established WebSocket connection. After the connection gets disconnected, the server will automatically mark that device as “offline”. Upon reconnect, the client has to announce and subscribe for presence events again. In rare cases, there can be a delay of up to 15 minutes after disconnect before the server acknowledges and marks that device as “offline”. The user will only appear offline if all its devices are disconnected or haven’t announced their status.

Announcing & Updating Presence

Upon (re)connecting the WebSocket, the client must announce its presence status if it wishes to appear available to other clients. This is accomplished by invoking the Presence.update method. The method can also be used to set the client into an “invisible” state in which it appears as offline until explicitly changed to “available”. Advisory values of “busy” and “away” may also be set. When a client is available, busy or away, it continues to update the last_seen_at timestamp and appears as online.

The client may update its status using the “auto” value. In that case the server will set the status to either the last set status for that user or to “available”, if the user has never set a status before. The server will send the change back after it is applied. If the client sets status using “auto”, the server will send back the change with the status value that was already set (either the last set status, “available” or “invisible”) and update last_seen_at.

If a client sets the presence status to “invisible”, it will appear “offline” to other users and the last_seen_at field will not be updated by the server. The user can make themselves visible again by explicitly updating the status to “available”, “away” or “available”. The “auto” status will not change the users visibility.

The last set status and last_seen_at from whichever device are the users current presence state on all of their devices

{
  "type": "request",
  "body": {
    "request_id": "680c036f-da7d-42a7-b3e0-1c6de6c75ccd",
    "method": "Presence.update",
    "data": [
      { "operation": "set", "property": "status", "value": "available" }
    ]
  }
}

Response

{
  "type": "response",
  "sent_at": "2014-09-15T04:45:00+00:00",
  "body": {
    "request_id": "680c036f-da7d-42a7-b3e0-1c6de6c75ccd",
    "method": "Presence.update",
    "success": true,
    "data": null
  }
}

Subscribing to Presence Events

Connected clients will not receive presence updates until they explicitly subscribe to events. This is accomplished by invoking the Presence.subscribe method.

Request

{
  "type": "request",
  "body": {
    "request_id": "cf8317dd-f59b-4372-aa66-6964433b773a",
    "method": "Presence.subscribe",
  }
}

Response

{
  "type": "response",
  "sent_at": "2014-09-15T04:45:00+00:00",
  "body": {
    "request_id": "cf8317dd-f59b-4372-aa66-6964433b773a",
    "method": "Presence.subscribe",
    "success": true,
    "data": null
  }
}

Receiving Presence Events

Presence events are published as object changes to the Identity object that they are associated with. Users need to follow other users in order to receive their presence changes.

{
  "type": "change",
  "counter": 1,
  "sent_at": "2017-01-19T09:15:43+00:00",
  "body": {
    "operation": "update",
    "object": {
      "type": "Identity",
      "id": "layer:///identities/f3cc7b32-3c92-11e4-baad-164230d1df67",
      "url": "https://api.layer.com/identities/f3cc7b32-3c92-11e4-baad-164230d1df67"
    },
    "data": [
      { "operation": "set", "property": "presence.status", "value": "available" },
      { "operation": "set", "property": "presence.last_seen_at", "value": "2017-01-19T01:22:35Z" }
    ]
  }
}

Subscribing to events and receiving the user’s current state using the “auto” status

The easiest way to initialize the user’s status, is by setting the status using auto.

  1. Subscribe to presence updates. You should subscribe to updates first in order to receive your own update.
  2. Set presence status to auto
  3. Receive the current presence status

Example:

The following example assumes the users id is alice.

Subscribe Request

{
  "type": "request",
  "body": {
    "request_id": "cf8317dd-f59b-4372-aa66-6964433b773a",
    "method": "Presence.subscribe",
  }
}

Response

{
  "type": "response",
  "sent_at": "2017-04-14T04:45:00+00:00",
  "body": {
    "request_id": "cf8317dd-f59b-4372-aa66-6964433b773a",
    "method": "Presence.subscribe",
    "success": true,
    "data": null
  }
}

Update Request

{
  "type": "request",
  "body": {
    "request_id": "680c036f-da7d-42a7-b3e0-1c6de6c75ccd",
    "method": "Presence.update",
    "data": [
      { "operation": "set", "property": "status", "value": "available" }
    ]
  }
}

Response

{
  "type": "response",
  "sent_at": "2017-04-14T04:45:01+00:00",
  "body": {
    "request_id": "680c036f-da7d-42a7-b3e0-1c6de6c75ccd",
    "method": "Presence.update",
    "success": true,
    "data": null
  }
}

Update

{
  "type": "change",
  "counter": 1,
  "sent_at": "2017-04-14T04:45:01+00:00",
  "body": {
    "operation": "update",
    "object": {
      "type": "Identity",
      "id": "layer:///identities/alice",
      "url": "https://api.layer.com/identities/alice"
    },
    "data": [
      { "operation": "set", "property": "presence.status", "value": "available" },
      { "operation": "set", "property": "presence.last_seen_at", "value": "2017-04-14T04:45:00Z" }
    ]
  }
}

The device is now subscribed to presence, and the status is updated without overriding it.

Retrieving Presence for Followed Users

Presence state for the followees of the authenticated user can be retrieved by invoking the Presence.sync method.

Parameters

Name Type Description
since Optional date Retrieve presence updates that have a last_seen_at greater than since
ids List of Identity URI Retrieve presence updates for specific users

since and ids are mutually exclusive.

Request

{
  "type": "request",
  "body": {
    "method": "Presence.sync",
    "request_id": "e67b5da2-95ca-40c4-bfc5-a2a8baaeb50f",
    "data": {
      "since": "2017-01-11T01:05:08Z"
    }
  },
}

Response

As the Presence.sync method may return an arbitrarily large number of objects, the response may be batched. When a response is batched, the data payload will contain a nested batch structure detailing the number of batches forthcoming.

{
  "type": "response",
  "timestamp": "2014-09-15T04:45:00+00:00",
  "body": {
    "method": "Presence.sync",
    "request_id": "e67b5da2-95ca-40c4-bfc5-a2a8baaeb50f",
    "success": true,
    "data": {
      "changes": [
        {
          "operation": "update",
          "object": {
            "type": "Identity",
            "id": "layer:///identities/alice",
            "url": "https://api.layer.com/identities/alice"
          },
          "data": [
            {
              "operation": "set",
              "property": "presence.status",
              "value": "available"
            },
            {
              "operation": "set",
              "property": "presence.last_seen_at",
              "value": null
            }
          ]
        },
        {
          "operation": "update",
          "object": {
            "type": "Identity",
            "id": "layer:///identities/bob",
            "url": "https://api.layer.com/identities/bob"
          },
          "data": [
            {
              "operation": "set",
              "property": "presence.status",
              "value": "available"
            },
            {
              "operation": "set",
              "property": "presence.last_seen_at",
              "value": null
            }
          ]
        }
      ],
      "batch": {
        "index": 0,
        "count": 1
      }
    }
  }
}

Alternatively, clients may specify exactly which user’s presence they would like to retrieve. They can do this via the Presence.sync method with the ids parameter. It is not possible to use both since and ids in the same request.

Request

{
  "type": "request",
  "body": {
    "method": "Presence.sync",
    "request_id": "e67b5da2-95ca-40c4-bfc5-a2a8baaeb50f",
    "data": {
      "ids": ["layer:///identities/alice", "layer:///identities/bob"]
    }
  },
}

Response:

Depending on the number of requested objects, the server might return the response in batches.

{
  "type": "response",
  "timestamp": "2014-09-15T04:45:00+00:00",
  "body": {
    "method": "Presence.sync",
    "request_id": "e67b5da2-95ca-40c4-bfc5-a2a8baaeb50f",
    "success": true,
    "data": {
      "changes": [
        {
          "operation": "update",
           "object": {
            "type": "Identity",
            "id": "layer:///identities/alice",
            "url": "https://api.layer.com/identities/alice"
          },
          "data": [
            {
              "operation": "set",
              "property": "presence.status",
              "value": "available"
            },
            {
            	"operation": "set",
            	"property": "presence.last_seen_at",
            	"value": null
            }
          ]
        },
        {
          "operation": "update",
          "object": {
          	"type": "Identity",
          	"id": "layer:///identities/bob",
          	"url": "https://api.layer.com/identities/bob"
          },
          "data": [
            {
              "operation": "set",
              "property": "presence.status",
              "value": "available"
            },
            {
              "operation": "set",
              "property": "presence.last_seen_at",
              "value": null
            }
          ]
        }
      ],
      "batch": {
      	"index": 0,
      	"count": 1
      }
    }
  }
}

Response batching

Batches are used when the server needs to send you multiple pages of results. If batches are used, the result includes a batch property that indicates:

Name Type Description
count integer How many batches (i.e. pages) of responses to expect
index integer Which page/batch this current response contains

First response

In this example, you can see that you should expect 2 batches in total and that this is the first packet.

{
  "batch": {
    "index": 0,
    "count": 2
  }
}

Second response

By looking at the index and count, you can see that this is the second and the last batch packet.

{
  "batch": {
    "index": 1,
    "count": 2
  }
}