Generating and Sharing Status Updates

The globaliD system allows users to associate a status with their identity. The identity's status can change over time, and there can be different types of status in effect at any one time.

A status update is simply a record of the identity's status at a given point in time. A typical status update might look like the following:

   {
     "uuid": "...",
     "gid_uuid": "...",
     "created_at": "...",
     "uploaded_at": "...",
     "type": "available for work",
     "source": "web",
     "payload": {
       "available": false
     }
   }

Each status update has a type that tells you what is being updated, along with a payload that contains the actual information associated with this status update. In this example, the identity is changing their "available for work" status, marking themselves as unavailable for work.

Status updates are sent to the globaliD Status API, where they are stored. Unless the user chooses to delete their previous status updates, the uploaded status updates paint a picture of the identity's ongoing changes in status over time.

Status updates can be used for all sorts of things, including:

  • Availability for work.
  • Health stats such as heart rate, blood sugar levels, etc.
  • Location.
  • Exercise intensity.
  • App and OS versions.
  • etc.

While the user who uploaded a status update can always retrieve their own status update again, it is far more useful and interesting to share your status updates with other people. Status updates can be selectively shared with a single person, with a group of people, with all your contacts, or with everyone. When you have shared one or more status updates with someone, they can view those status updates, and also set up a persistent connection to the globaliD service so their app is notified whenever a new status update comes in, allowing for real-time sharing of status updates.

Uploading Status Updates

To upload one or more status updates, you call the POST /v1/status API endpoint. For example:

Request:

    POST /v1/status
  BEARER <access_token>

  [
    {
      "uuid": "...",
      "source": "...",
      "type": "...",
      "created_at": "...",
      "payload": {...}
    },
    ...
  ]

Response:

  HTTP/1.1 201 CREATED

  [
    {
      "uuid": "...",
      "source": "...",
      "type": "...",
      "created_at": "...",
      "payload": {...}
    },
    ...
  ]

As you can see, the created status updates are returned. Each status update that you upload must include the following:

  • uuid: a UUID value that uniquely identifies this status update.
  • source: a string identifying the source of the status update.
  • type: a string identifying the type of status update.
  • created_at: the date and time at which the status update was created, in ISO-8601 format.
  • payload: an object holding any additional information associated with this status update.

Note that you need to generate a UUID for the status update, and also provide a created_at value. This is because the status updates might be generated sometime ahead of when they are uploaded. For example, if your app continuously records status updates (for example, the user's heart rate and GPS location during a bicycle race), your app may not be able to upload those status updates immediately. The date and time at which each status update was created is recorded, separately from when it was uploaded to the globalID servers.

Also, because each status update has its own UUID value, the API is able to gracefully handle the situation where status updates are uploaded more than once. If your app is attempting to upload a number of status updates, and the device loses its network connection halfway through, there is no way of knowing if the status updates were uploaded or not. To allow for this, your app can simply upload them again, and any duplicates will be discarded. This is why you have to calculate a UUID for each status update yourself.

Retrieving Status Updates

As the creator of status updates, an identity is always able to retrieve them again. This is done using the GET /v1/status API endpoint:

Request:

   GET /v1/status
   BEARER <access_token>

Response:

   HTTP/1.1 200 OK

  [
    {
      "uuid": "...",
      "source": "...",
      "type": "...",
      "created_at": "...",
      "payload": {...}
    },
    ...
  ]

The results are a single page of status updates. By default, 50 status updates are returned, though this can be adjusted using the per_page query-string parameter.

By using the page query-string parameter, you can call this endpoint repeatedly to download all the status updates. For example:

`GET /v1/status?per_page=100&page=1`
`GET /v1/status?per_page=100&page=2`
`GET /v1/status?per_page=100&page=3`
etc.

You simply keep incrementing the page parameter until no more status updates are returned.

Additional query-string parameters can be used to only return a subset of the status updates:

  • source: only return status updates with the given source value.
  • type: only return status updates with the given type.
  • start: only include status updates generated after the given date and time.
  • end: only include status updates generated before the given date and time.

Deleting Status Updates

As the owner of status updates, you can delete them at any time. To do this, you call the DELETE /v1/status API endpoint:

Request:

    DELETE /v1/status
    BEARER <access_token>

Response:

   HTTP/1.1 204 NO CONTENT

By default, all the uploaded status updates will be deleted. To only delete a subset of your status updates, you can use the following query-string parameters:

  • source: only delete the status updates with the given source value.
  • type: only delete the status updates with the given type.
  • start: only delete status updates generated after the given date and time.
  • end: only delete status updates generated before the given date and time.

Creating Permissions

To share status updates with others, you create Permission records. To do this, use the POST /v1/status/permissions API endpoint:

Request:

   POST /v1/status/permissions
   BEARER <access_token>

   {
     "source": "...",
     "type": "...",
     "recipient_type": "individual",
     "recipient_uuid": "..."
   }

Response:

   HTTP/1.1 201 CREATED

   {
     "gid_uuid": "...",
     "source": "...",
     "type": "...",
     "recipient_type": "individual",
     "recipient_uuid": "...",
     "created_at": "...",
     "updated_at": "...",
     "valid_from": "...",
     "valid_to": "..."
   }

The Permission record identifies which status updates are covered by the permission, and who to share them with. To identify the status updates, the following fields are used:

  • source: only share status updates with the given source. If this has the value "*", then all sources will be included.
  • type: only share status updates with the given type. If this has the value "*", then all types are included.
  • valid_from: only share status updates generated after this date. If this is blank, this value will not be used to filter the set of matching status updates. If specified, this value should be in ISO-8601 format.
  • valid_to: only share status updates generated before this date. If this is blank, this value will not be used to filter the set of matching status updates. If specified, this value should be in ISO-8601 format.

To identify who to share the matching status updates with, the recipient_type and recipient_uuid fields are used:

  • To share the matching status updates with everyone, set the recipient_type field to the value "all". In this case, the recipient_uuid field is ignored.
  • The share the matching status updates with all your contacts, set the recipient_type field to "contacts". Once again, the recipient_uuid field is ignored.
  • To share the matching status updates with all members of a given globaliD group, set recipient_type to "group", and set recipient_uuid to the gid_uuid of the group.
  • To share the matching status updates with just one identity, set recipient_type to "individual", and set recipient_uuid to the gid_uuid of the identity you wish to share these status updates with.

Retrieving Permissions

To see what permission records are current in effect, you can call the GET /v1/status/permissions API endpoint:

Request:

   GET /v1/status/permissions
   BEARER <access_token>

Response:

   HTTP/1.1 200 OK

   [
     {
       "id": "..."
       "gid_uuid": "...",
       "source": "...",
       "type": "...",
       "recipient_type": "individual",
       "recipient_uuid": "...",
       "created_at": "...",
       "updated_at": "...",
       "valid_from": "...",
       "valid_to": "..."
     },
     ...
   ]

The id field holds the unique ID for each permission, while the gid_uuid field holds the gid_uuid of the identity that created this permission. The other fields are the same as those set up when creating the permission.

By default, a single page of permissions is returned. The number of permissions per page can be controlled by using the per_page parameter, and you can retrieve additional pages of permissions using the page parameter, like this:

`GET /v1/permissions?per_page=100&page=1`
`GET /v1/permissions?per_page=100&page=2`
etc.

Updating Permissions

To update a Permission record, you use the PUT /v1/status/permissions/<permission_id> endpoint, like this:

Request:

   PUT /v1/status/permissions/<permission_id>
   BEARER <access_token>

   {
     ...
   }

Response:

   HTTP/1.1 202 Accepted

<permission_id> should be the ID of the permission to update, as returned in the id field when downloading a permission.

The body of the request can contain the various fields to be updated. The following fields in the Permission record can be changed:

  • source
  • type
  • valid_from
  • valid_to
  • recipient_type
  • recipient_uuid

Deleting Permissions

To delete a Permission record, call the DELETE /v1/status/permissions/<permission_id> endpoint:

Request:

   DELETE /v1/status/permissions/<permission_id>
   BEARER <access_token>

Response:

   HTTP/1.1 204 No Content

<permission_id> should be the ID of the permission to update, as returned in the id field when downloading a permission.

Retrieving Shared Status Updates

To retrieve the status updates that others have shared with an identity, you can call the GET /v1/status/shared API endpoint. For example:

Request:

   GET /v1/status/shared
   BEARER <access_token>

Response:

   HTTP/1.1 200 OK

   [
     {
       "uuid": "...",
       "gid_uuid": "...",
       "source": "...",
       "type": "...",
       "created_at": "...",
       "payload": {...}
    },
    ...
  ]

Each shared status update will include the following information:

  • uuid: the unique UUID value for this status update.
  • gid_uuid: the UUID of the identity that generated this status update.
  • source: the source value for this status update.
  • type: the type of status update.
  • created_at: when this status update was created.
  • payload: an object containing the optional payload associated with this status update, if any.

The endpoint returns an array containing a single page of shared status updates. You can change the number of status updates per page using the per_page query-string parameter, like this:

`GET /v1/status/shared?per_page=100`

To retrieve all the status updates which have been shared with the identity, you call the endpoint repeatedly, setting the page parameter to an incrementing value, until no more status updates are returned. For example:

`GET /v1/status/shared`
`GET /v1/status/shared?page=2`
`GET /v1/status/shared?page=3`
...etc

By default, all the status updates which have been shared with you will be returned. If you wish, you can filter the results using the following query-string parameters:

  • start: only include status updates created on or after the given ISO-8601 formatted date and time.
  • end: only include status updates created on or before the given ISO-8601 formatted date and time.
  • source: only include status updates with the given source value.
  • type: only include status updates with the given type.
  • shared_by: only include status updates generated by the given identity. The value should be the gid_uuid value of the identity.

Finally, you can use the since_uuid query-string parameter to poll for any status updates which have been shared with you since the last time you checked. To do this, you remember the UUID of the last status updates you received, and pass this value to the API. For example:

`GET /v1/status/shared?since_uuid=4470009d-ca3c-4819-aa3a-7fa04e9af258`

If any new shared status updates have been uploaded since that status update was received, they will be returned (up to a maximum of 50). Otherwise, the API endpoint will simply return an empty array.

This allows you to regularly poll for new status updates which have been shared with the identity.

While polling works and is an easy solution, it is not particularly scalable. For real-time delivery of shared status updates, you should use websockets, as described in the following section.

Using Websockets for Real-Time Status Sharing

Using websocket technology, it is possible to open a persistent connection to the globaliD status API so that newly shared status updates are delivered instantly. This is done using the socket.io library; simply install a suitable socket.io client library for your language and platform, and use it to open a websocket to the status API, like this:

    var io = require('socket.io-client')
    var socket = io.connect('https://api.global.id, {path: '/v1/socket/'})

Upon opening the socket, the client should emit a LISTEN event, like this:

    socket.on('connect', function() {
        socket.emit('LISTEN', {access_token, gid_uuid, filters})
    })

access_token should be set to the listening identity's access token, and gid_uuid should be the UUID of the listening identity. filters can either be the special value '*', which tells the sever to send through all status updates, or an array of (type, source) arrays indicating the types and sources of status updates to be downloaded.

Once this has been done, the socket will be associated with the given identity, and any new status updates which have been shared with that identity will be sent through the websocket in the form of a STATUS_UPDATE event. Your socket client can listen for this event, for example:

    socket.on('STATUS_UPDATE', function(status_update) {
      ...      
    })

status_update will be an object with the following fields:

  • uuid: the unique UUID value for this status update.
  • gid_uuid: the UUID of the identity that generated this status update.
  • source: the source value for this status update.
  • type: the type of status update.
  • created_at: when this status update was created.
  • payload: an object containing the optional payload associated with this status update, if any.

Your app can then process this received status update in whatever way it wants.