How to: Manage Status

Managing integration status and heartbeats


Introduction

Before we get to the good stuff (uploading assets), there are three more “housekeeping” API endpoints we need to discuss. In this Guide we will go over how to:

  • Emit heartbeats to let Frame.io know the device is still ‘online’.
  • Fetch information about a device connection.
  • Check if the Frame.io backend is reachable.

What will I need?

If you haven’t read the Implementing C2C: Setting Up guide, give it a quick glance before moving on!

You will also need the access_token you received during the hardware device or C2C Application authentication and authorization guide.

Emitting heartbeats

In the C2C Connections tab of your Frame.io project, you will see that your device has an online or offline status. When the device is online, a small green indicator will light up in the top-left corner of the device card. When the device is offline, the UI of the card will become greyed-out.

If Frame.io’s servers do not hear from your device for five minutes, its status will change to offline. Whenever you interact with any https://api.frame.io endpoint, the five-minute timer will reset. Note that this means authentication actions taken on https://applications.frame.io and uploading file chunks to AWS S3 URLs will not reset this timer.

If your device goes for more than 5 minutes without making a call to our servers, then it is in danger of appearing offline even, if it is not. We don’t want your device to appear inattentive or lazy!

To avoid such shame, you need to set up your device to emit a heartbeat at regular intervals. This interval should be no less than 60 seconds, and no more than 300 seconds (5 minutes). We recommend 120 seconds (two minutes).

To emit a heartbeat, make the following call:

Shell
curl -X POST https://api.frame.io/v2/devices/heartbeat \
    --include \
    --header 'Authorization: Bearer [access_token]'
API endpoint specificaton

Docs for /v2/devices/heartbeat can be found here

The Authorization header

For every end point that requires authorization, we need to add the access_token to the Authorization header. Notice that we need to pre-append Bearer (with a space!) to our access token as the value.

You should get a 204 response code, which means the heartbeat was accepted and our internal timer was reset:

HTTP/2 204
...

That’s it! We recommend launching a thread / async task / cron job in your integration to make this call:

Python
def heartbeat_task():
    """
    Task that emits heartbeats every 120 seconds.
    """

    while True:
        c2c.emit_heartbeat()
        sleep(120)

Advanced integrations could reset their own heartbeat timers whenever a call is made to api.frame.io if they wish to keep network chatter to an absolute minimum. In reality one heartbeat every 2-4 minutes should not add a meaningful strain to a network, but if you are regularly polling the device information detailed below, you may not need to emit heartbeats directly very often.

A more advanced task might look like this:

Python
def heartbeat_middleware(next_handler):
    """
    C2C call middleware that updates that last time the device interacted with the 
    backend.
    """

    def call_handler(call):
        result = next_handler(call)
        # Only updates on calls to `api.frame.io`.
        if call.host == "api.frame.io":
            c2c.LAST_INTERACTION = datetime.now()
        return result

    return call_handler

def heartbeat_task():
    """
    Task that emits heartbeats every 120 seconds if the device has not interacted
    with Frame.io's servers.
    """

    while True:
        seconds_since_interaction = (datetime.now() - c2c.LAST_INTERACTION).seconds
        seconds_remaining = 120 - seconds_since_interaction

        if seconds_remaining > 0:
            sleep(seconds_remaining)
        else:
            c2c.emit_heartbeat()

Handling of graceful shutdown / errors is left as an exercise to the reader. Error handling will be discussed in-depth in a later guide. As always, reach out if you have questions regarding how to set up heartbeats.

Fetching connection information

We can fetch information about our connection by making the following call:

Shell
curl -X GET https://api.frame.io/v2/devices/me \
    --header 'Authorization: Bearer [access_token]' \
    | python -m json.tool
API endpoint specificaton

Docs for /v2/devices/me can be found here

We should get a response like so (some data elided):

JSON
{
    "_type": "project_device",
    "asset_type": "video",
    "authorization": {
        "_type": "project_device_authorization",
        "creator": {
            "_type": "user",
            "id": "e7e96254-8bd6-4d59-b54d-28c58570a8de",
            "name": "Harry Potter"
        },
        "expires_at": null,
        "id": "7b2b68e5-788d-497c-8597-f9362cb1a75e",
        ...
        "project_device_id": "14856308-46e0-4d7d-8438-320262eec74e",
        "scopes": {
            ...
            "asset_create": true,
            ...
            "id": "0fe0accb-447f-44f6-b2af-177d913b3a29",
            "offline": true,
            ...
        }
    },
    "channels": [
        {
            "_type": "project_device_channel",
            "asset_type": "video",
            "external_index": 0,
            ...
        }
    ],
    ...
    "name": "Frameio-BPEAKE-TEST-DEVICE",
    "project": {
        "_type": "project",
        "id": "2ad59fe6-77b6-4ffc-a9d2-3dd0413ed4a3",
        "name": "Testbed"
    },
    "project_id": "2ad59fe6-77b6-4ffc-a9d2-3dd0413ed4a3",
    "status": "online",
    ...
}

We can use this endpoint to verify the project we are connected to, as well as who originally authorized the device. We should display the following to the user:

  • project.name - The name of the project we are connected to.
  • authorization.creator.name - The user who originally paired / authorized the device.
  • authorization.expires_at (optional) - When the device connection expires (can be set at any time).
  • status (optional) - The status of the device. Can be:

    • online - The device is online and paired.
    • offline - The device has not emitted any activity in more than 5 minutes, although the act of invoking this endpoint will cause the status to change to online as soon as the response is returned.
    • paused - The device has been paused in the C2C Connections tab of Frame.io.

Because expiration time / paused state can be set at any point in Frame.io, it’s a good idea to periodically poll this information if you wish to display it to the user. We ask that you do not poll this endpoint more than once every 60 seconds.

Displaying the device status

The status returned in the identity payload should not be displayed directly. online or offline is not meaningful to the end user, as it only indicates whether the device has communicated to our backend within the last 5 minutes.

Status should really be broken into two fields:

  • Paused: true / false - If the status field above is paused, the should display true, otherwise false.
  • Connected: true / false - Whether the device can reach the backend (see backend connection status below).

Handling the paused status

You are not required to display the paused status to the user, but if you choose to do so, it is important you understand how this status works.

The paused status is meant to block sensitive content created during a window of time. It is not designed to block network traffic. Imagine you are on set and about to film a scene that contains nudity. An Actor, Director, or Producer might request that this footage not make its way to Frame.io to protect the actors’ privacy. Instead of completely disconnecting your C2C devices, you can simply pause them, and any footage created between the time the device is paused to the time it is unpaused will be rejected from upload.

Pausing a device is done in the Frame.io UI on our end, and is not an input you as an integrator are responsible for.

While a device is paused, if there is queued media that was created during an unpaused window, such media can still be uploaded.

You should not use the identity endpoint to validate whether you can upload a piece of media. Our backend does that for you! We’ll go over handling the paused status for uploads in the advanced uploading guide. In this guide, we simply want to know how to display the status:

  • If you get a 409 error from uploading a recent asset, fetch the connection info to see if you are currently paused, then display that status to the user. You may get a 409 for an older piece of media that was made during a past pause window. Don't assume that because you get a 409, the device is currently paused.
  • If you are currently displaying a paused status, and are able to create a new asset, fetch the connection info and see if you have been unpaused (status will be online or offline), and update the status for the user. Don't assume that because you are able to upload a new piece of media, your device is unpaused. You may have just uploaded a piece of media that was created during an unpaused window.

In general, we ask that your devices not be overly chatty with our server. If you decide to poll for paused status, please do not do so more than once every 60 seconds unless uploading a file indicates that the status might have changed.

Backend connection status

If you want to check whether or not you can communicate to Frame.io, you can make a call to the following endpoint:

Shell
curl -X GET https://api.frame.io/health \
    | python -m json.tool

This endpoint does not require authorization. If you are able to communicate to the server, you should get:

JSON
{
    "ok": true
}

Using https://api.frame.io/health can be useful for checking connected status since it ensures you can communicate with Frame.io specifically. There may be cases where your network is up and connected, but Frame.io is unreachable, either due to a problem on our end or because a portion of the internet is down that Frame.io relies on.

Next up

If you haven’t already, we encourage you to reach out to our team, then continue to the next guide. We look forward to hearing from you!