Anbox Stream Gateway API Reference

The Anbox Stream Gateway provides federated access to Anbox Cloud regions. It's primary purpose is it to connect clients to individual Android containers and enable WebRTC based streaming. Tt does so via sessions which are 'chatrooms' for clients and stream providers to communicate. When the communication is established, the stream is sent directly from one peer to another.

The Anbox Stream Gateway keeps things simple and only manages what is required to make streaming happen. Other components can invoke its REST API to add other capabilities on top such as user management, limiting, etc.

Authentication

All calls to the Stream Gateway must be authenticated. Authentication takes the form of a single token per client you must embed in your requests

1. Creating the token

An internal HTTP API is exposed for managing client tokens. This API is only accessible via a Unix domain socket which resides at /var/snap/anbox-stream-gateway/common/service/unix.socket by default.
For convenience, the Stream Gateway has a built-in client designed to communicate to that API.

Creating a token

$ anbox-stream-gateway account create my-client
AgEUYW5ib3gtc3RyZWFtLWdhdGV3YXkCBGFzZGYAAhkyMDIwLTA2LTIzVDA5OjMyOjE5KzAyOjAwAAAGIDcZMdTrdNdJB6kzjoXyx1_T6s8-0C1AQSyzaA_GHLYQ

Deleting a token

$ anbox-stream-gateway account delete my-client
Account my-client deleted successfully

You can type anbox-stream-gateway --help to list all commands

2. Using the token in your requests

When making requests to the Stream Gateway API you can either place the token in the request HTTP headers or in the query parameters.

Request headers

$ curl -X GET https://20.234.75.29:4000/1.0/sessions \
        -H 'authorization=macaroon root=AgEUYW5ib3...QSyzaA_GHLYQ'

Query parameters

$ curl -X GET https://20.234.75.29:4000/1.0/sessions?api_token=AgEUYW5ib3...QSyzaA_GHLYQ
Contact: indore@lists.canonical.com
Version: 1.0

application

Get applications

GET /1.0/applications

Return all applications that were registered via AMS and that support streaming.

List of applications

Response Example (200 OK)
{
  "metadata": [
    {
      "name": "com.foo.bar"
    }
  ]
}

region

Get regions

GET /1.0/regions

Regions are cloud regions, allowing clients to be as close as possible to the agent running the Android container.

The list is dynamic and regions might change as agents are added or removed.

Response Example (200 OK)
{
  "metadata": [
    {
      "name": "eu-west-1"
    }
  ]
}

session

Join session as master

GET /1.0/session/{id}/sockets/master

A websocket connection endpoint which initiates the signaling process with the master role. A master provides the stream where a slave consumes it. In a typical setup, the container calls the master endpoint, and the client calls the slave endpoint. You MUST call /sessions/{id}/join beforehand to prepare the android container.

Join session as slave

GET /1.0/session/{id}/sockets/slave

A websocket connection endpoint which initiates the signaling process with the slave role. Slaves are on the receiving end of the streaming. In a typical setup, the container calls the master endpoint, and the client calls the slave endpoint. This URL is returned then joining a session along with its credentials.

Get all sessions

GET /1.0/sessions
status: string
in query

Filter returned sessions by given status

recursive: boolean
in query

Return full session objects rather than just their ID

500 Internal Server Error

Internal Server Error

Response Content-Types: application/json
Response Example (200 OK)
{
  "metadata": [
    "string"
  ]
}
Response Example (500 Internal Server Error)
"#/definitions/api.Response"

Create session

POST /1.0/sessions

Create a new session based on an application, application version, region and screen details. The newly created session is started immediately after being created. The returned session details can be used to immediately start the signaling process. If an application version is not specified, the latest application version will always be in use for a session creation.

Session details

Request Content-Types: application/json
Request Example
{
  "app": "com.foo.bar",
  "app_version": 0,
  "ephemeral": false,
  "extra_data": "userid=123",
  "idle_time_min": 5,
  "joinable": true,
  "region": "us-west-1",
  "screen": {
    "density": 240,
    "fps": 25,
    "height": 720,
    "width": 1280
  }
}

Newly created session along with the information needed to connect to it

400 Bad Request

Invalid body or missing application

404 Not Found

No agent can host the container

500 Internal Server Error

Internal Server Error

Response Content-Types: application/json
Response Example (201 Created)
{
  "metadata": {
    "id": "e25f3e3bcead096461d89d8ab7043f14bdb1ecd39",
    "joinable": true,
    "region": "eu-west-2",
    "status": "active",
    "stun_servers": [
      {
        "password": "3f14bdb1ecd3",
        "urls": [
          "https://stun.foo.com",
          "https://turn.foo.com"
        ],
        "username": "f3e3bcead096461d8"
      }
    ],
    "url": "string"
  }
}
Response Example (400 Bad Request)
"#/definitions/api.Response"
Response Example (404 Not Found)
"#/definitions/api.Response"
Response Example (500 Internal Server Error)
"#/definitions/api.Response"

Batch delete sessions

DELETE /1.0/sessions

List of session IDs to delete

force: boolean
in query

Force deletion even if agent is not available. This may leave a container around on the agent.

sync: boolean
in query

Set to true to wait for the response (can take a long time for lots of sessions) or to false to return without waiting for all sessions to be deleted. Defaults to false

Request Example
{
  "ids": [
    "string"
  ]
}

Contains an array of deleted sessions as well as potential errors

202 Accepted

Returned when sync=true. Watch the session list for progress on the operation

207 Multi-status

Some sessions could not be deleted

400 Bad Request

Invalid request body

404 Not Found

Non-existent sessions

500 Internal Server Error

Internal issue

Response Example (200 OK)
{
  "metadata": {
    "deleted_sessions": [
      "string"
    ],
    "errors": [
      {
        "error_message": "string",
        "session_id": "string",
        "status_code": "integer"
      }
    ]
  }
}
Response Example (202 Accepted)
"#/definitions/api.Response"
Response Example (207 Multi-status)
"#/definitions/api.Response"
Response Example (400 Bad Request)
"#/definitions/api.Response"
Response Example (404 Not Found)
"#/definitions/api.Response"
Response Example (500 Internal Server Error)
"#/definitions/api.Response"

Get session

GET /1.0/sessions/{id}

Returns a session from its ID.

id: string
in path

Session ID

The requested session

400 Bad Request

Invalid session ID

404 Not Found

Non-existent session

Response Content-Types: application/json
Response Example (200 OK)
{
  "metadata": {
    "app": "string",
    "container_id": "c05h1jj3pn6a8q46taug",
    "id": "e25f3e3bcead096461d89d8ab7043f14bdb1ecd39",
    "joinable": "boolean",
    "region": "eu-west-1",
    "status": "string",
    "status_message": "Container failed to start"
  }
}
Response Example (400 Bad Request)
"#/definitions/api.Response"
Response Example (404 Not Found)
"#/definitions/api.Response"

Delete a session

DELETE /1.0/sessions/{id}
id: string
in path

Session ID

force: boolean
in query

Force deletion even if agent is not available. This may leave a container around on the agent.

sync: boolean
in query

Set to true to wait for the response or to false to return early without waiting for the session to be deleted

200 OK

Empty response to indicate success

400 Bad Request

Invalid session ID

404 Not Found

Non-existent session

500 Internal Server Error

Internal Server Error

Response Example (200 OK)
"#/definitions/api.Response"
Response Example (400 Bad Request)
"#/definitions/api.Response"
Response Example (404 Not Found)
"#/definitions/api.Response"
Response Example (500 Internal Server Error)
"#/definitions/api.Response"

Join session

POST /1.0/sessions/{id}/join

Join an existing running session. The session must already be running. The returned object contains a URL with the required credentials for a client to join the signaling process.

Additional information about the join request

Request Example
{
  "disconnect_clients": true
}

Object containing the slave URL as well as optional additional STUN/TURN servers

400 Bad Request

Missing session ID or invalid session state

404 Not Found

The session does not exist

500 Internal Server Error

Error when trying to generate session details

Response Example (200 OK)
{
  "metadata": {
    "stun_servers": [
      {
        "password": "3f14bdb1ecd3",
        "urls": [
          "https://stun.foo.com",
          "https://turn.foo.com"
        ],
        "username": "f3e3bcead096461d8"
      }
    ],
    "url": "https://api.example.com/1.0/session/e25fcd39/sockets/slave?token=foobar"
  }
}
Response Example (400 Bad Request)
"#/definitions/api.Response"
Response Example (404 Not Found)
"#/definitions/api.Response"
Response Example (500 Internal Server Error)
"#/definitions/api.Response"

status

Returns the Gateway service status.

GET /1.0/status

Returns the current status of the Gateway service along with some indicators that can be helpful to determine larger issues. The Gateway can be either healthy or unhealthy. Please note that a healthy status does not necessarily mean that a deployment is fully working. Other issues can affect the Streaming Stack but a healthy status only guarantees that the Gateway itself is not experiencing issues that would prevent it from working normally. Checking for status can take up to 7 seconds. Note that this is the upper bound, in normal circumstances, the timing will be much lower and timings higher than a couple seconds are usually indicators or something wrong (network issue, node restarted, etc).

Only status is present if the request is not authenticated

500 Internal Server Error

Internal Server Error

503 Service Unavailable

The Gateway is not fully started

Response Content-Types: application/json
Response Example (200 OK)
{
  "metadata": {
    "agents": "integer",
    "database_nodes": "integer",
    "status": "string"
  }
}
Response Example (500 Internal Server Error)
"#/definitions/api.Response"
Response Example (503 Service Unavailable)
"#/definitions/api.Response"

Schema Definitions

api.Application: object

name: string
Example
{
  "name": "com.foo.bar"
}

api.ApplicationsGetResponse: object

Example
{
  "metadata": [
    {
      "name": "com.foo.bar"
    }
  ]
}

api.Region: object

name: string
Example
{
  "name": "eu-west-1"
}

api.RegionsGetResponse: object

Example
{
  "metadata": [
    {
      "name": "eu-west-1"
    }
  ]
}

api.Response:

Example

api.Screen: object

density: integer x ≥ 72 240

Display density Android will be configured with. See https://developer.android.com/training/multiscreen/screendensities for more details

fps: integer x ≥ 1

FPS the video stream will use

height: integer x ≥ 1

Height of the screen

width: integer x ≥ 1

Width of the screen

Example
{
  "density": 240,
  "fps": 25,
  "height": 720,
  "width": 1280
}

api.Session: object

app: string

App that will be run in the session. Applications are listed from AMS if they have been configured for streaming.

container_id: string

ID of the container powering the session. If no container was created yet or the container is destroyed, the ID will be empty.

id: string

ID of the session.

joinable: boolean

Marks wether the session is joinable or not

region: string

Region on which the instance is located.

status: string created, active, error, terminating, terminated

Status of the session. created: sent creation request to an available agent. active: container is up and running. error: an error occurred and the container is stopped. terminated: the container has stopped gracefully, either by manual command or timeout.

status_message: string

Message giving more information about the current status

Example
{
  "app": "string",
  "container_id": "c05h1jj3pn6a8q46taug",
  "id": "e25f3e3bcead096461d89d8ab7043f14bdb1ecd39",
  "joinable": "boolean",
  "region": "eu-west-1",
  "status": "string",
  "status_message": "Container failed to start"
}

api.SessionGetResponse: object

metadata: api.Session
Example
{
  "metadata": {
    "app": "string",
    "container_id": "c05h1jj3pn6a8q46taug",
    "id": "e25f3e3bcead096461d89d8ab7043f14bdb1ecd39",
    "joinable": "boolean",
    "region": "eu-west-1",
    "status": "string",
    "status_message": "Container failed to start"
  }
}

api.SessionJoinPost: object

disconnect_clients: boolean

DisconnectClients disconnects all clients currently connected to the session if set to true. If set to false, connected clients will not be disconnected.

Example
{
  "disconnect_clients": true
}

api.SessionJoinResponse: object

Example
{
  "metadata": {
    "stun_servers": [
      {
        "password": "3f14bdb1ecd3",
        "urls": [
          "https://stun.foo.com",
          "https://turn.foo.com"
        ],
        "username": "f3e3bcead096461d8"
      }
    ],
    "url": "https://api.example.com/1.0/session/e25fcd39/sockets/slave?token=foobar"
  }
}

api.SessionJoinResponseData: object

stun_servers: api.StunServer

StunServers is a list of STUN servers with their optional credentials. They are passed to the client to figure out the best route to the actual android instance. They are used within the WebRTC protocol to negotiation a peer to peer transport between the Android instance and the connecting client.

api.StunServer
url: string

URL is the endpoint to reach to start the WebRTC signaling process.

Example
{
  "stun_servers": [
    {
      "password": "3f14bdb1ecd3",
      "urls": [
        "https://stun.foo.com",
        "https://turn.foo.com"
      ],
      "username": "f3e3bcead096461d8"
    }
  ],
  "url": "https://api.example.com/1.0/session/e25fcd39/sockets/slave?token=foobar"
}

api.SessionPost: object

app: string

Application the session should be created for

app_version: integer

Which specific version of the application to launch for the session. If not specified, the last published version is launched.

ephemeral: boolean true

Ephemeral controls whether the session should be deleted after the client disconnects or not. If the containers runs into an error, the session is kept if with Ephemeral set to true.

extra_data: string

Extra data passed as part of the userdata to the container

idle_time_min: integer

Time in minutes a session stays idle without any client connected. The value "0" is special and causes the container to stay alive until the session is terminated by an API call or the container decide on its own to shutdown.

joinable: boolean

Makes the session joinable by another client after the initial client left. Requires idle_time_min to be set.

region: string

Region the session should be created in. If left empty a region is randomly selected.

screen: api.Screen

Definition of the screen dimensions

Example
{
  "app": "com.foo.bar",
  "app_version": 0,
  "ephemeral": false,
  "extra_data": "userid=123",
  "idle_time_min": 5,
  "joinable": true,
  "region": "us-west-1",
  "screen": {
    "density": 240,
    "fps": 25,
    "height": 720,
    "width": 1280
  }
}

api.SessionPostResponse: object

Example
{
  "metadata": {
    "id": "e25f3e3bcead096461d89d8ab7043f14bdb1ecd39",
    "joinable": true,
    "region": "eu-west-2",
    "status": "active",
    "stun_servers": [
      {
        "password": "3f14bdb1ecd3",
        "urls": [
          "https://stun.foo.com",
          "https://turn.foo.com"
        ],
        "username": "f3e3bcead096461d8"
      }
    ],
    "url": "string"
  }
}

api.SessionPostResponseData: object

id: string

ID of the session.

joinable: boolean

Marks the session joinable after the initial client left

region: string

Region is a cloud region where the application will be launched. Regions are registered dynamically by agents.

status: string created, active, error, terminating, terminated

Status of the session. created: sent creation request to an available agent. active: container is up and running. error: an error occurred and the container is stopped. terminated: the container has stopped gracefully, either by manual command or timeout.

stun_servers: api.StunServer

StunServers is a list of STUN servers with their optional credentials. They are passed to the client to figure out the best route to the actual android instance. They are used within the WebRTC protocol to negotiation a peer to peer transport between the Android instance and the connecting client.

api.StunServer
url: string

URL is the endpoint to reach to start the WebRTC signaling process.

Example
{
  "id": "e25f3e3bcead096461d89d8ab7043f14bdb1ecd39",
  "joinable": true,
  "region": "eu-west-2",
  "status": "active",
  "stun_servers": [
    {
      "password": "3f14bdb1ecd3",
      "urls": [
        "https://stun.foo.com",
        "https://turn.foo.com"
      ],
      "username": "f3e3bcead096461d8"
    }
  ],
  "url": "string"
}

api.SessionsDelete: object

ids: string[]
string
Example
{
  "ids": [
    "string"
  ]
}

api.SessionsDeleteError: object

error_message: string

ErrorMessage contains information about the failure

session_id: string

SessionID is the id of the session that failed to be deleted

status_code: integer

StatusCode relevant to the error

Example
{
  "error_message": "string",
  "session_id": "string",
  "status_code": "integer"
}

api.SessionsDeleteResponse: object

metadata: object
deleted_sessions: string[]

DeletedSessions is the list of sessions IDs that were successfully deleted

string
errors: api.SessionsDeleteError

Errors, if not empty, contains the list of sessions that failed to be deleted

api.SessionsDeleteError
Example
{
  "metadata": {
    "deleted_sessions": [
      "string"
    ],
    "errors": [
      {
        "error_message": "string",
        "session_id": "string",
        "status_code": "integer"
      }
    ]
  }
}

api.SessionsGetResponse: object

metadata: string[]
string
Example
{
  "metadata": [
    "string"
  ]
}

api.StatusGetResponseAuthenticated: object

Example
{
  "metadata": {
    "agents": "integer",
    "database_nodes": "integer",
    "status": "string"
  }
}

api.StatusGetResponseAuthenticatedData: object

agents: integer
database_nodes: integer
status: string
Example
{
  "agents": "integer",
  "database_nodes": "integer",
  "status": "string"
}

api.StunServer: object

password: string

Password is the optional password to authenticate on the STUN/TURN server. It is usually unique to a session.

urls: string[]

URLs is the list of endpoints the STUN/TURN server can be reached on.

string
username: string

Username is the optional username to authenticate on the STUN/TURN server. It is usually unique to a session.

Example
{
  "password": "3f14bdb1ecd3",
  "urls": [
    "https://stun.foo.com",
    "https://turn.foo.com"
  ],
  "username": "f3e3bcead096461d8"
}