Dashboard API

Overview

The Dashboard API can be used to manipulate all objects found in Ducksboard: dashboards, widgets, external accounts, public access tokens and so on.

The API uses HTTPS exclusively and accepts and returns JSON. Access to the Dashboard API is through app.ducksboard.com.

An example request is:

curl -v -u APIKEY:x https://app.ducksboard.com/api/widgets/34

HTTP methods

You can use four HTTP methods when accessing API resources: GET, POST, PUT and DELETE.

GET requests

Return resources or collections of resources. See below for the specific format of each resource. When returning collections, the format is:

{
  "count": <integer>,
  "data": [
            <resource>
          ]
}
POST requests

Create new resources. The payload for a POST request should be an resource formatted according the the documentation below. Any extra fields are ignored. As noted for each specific resource, some fields are generated and cannot be specified by the caller and others will take on default values if not specified. POST requests typically return the created resource with generated fields filled in. Be sure to read the documentation to check which fields are omitted in the response.

The POST method is also used for some special endpoints, like regenerating the API key.

PUT requests
Update existing resources. The payload should be an resource formatted just like for a POST request and the response will be the entire new resource. If the payload is missing some fields, the resource being updated will keep the values for them, for instance dashboard resources have name and background fields. If you send just the name in your PUT request, the updated dashboard will keep its background and change its name. In this regard, PUT requests work like PATCH requests would.
DELETE requests
Delete resources. The payload is ignored and the return specifies the number of deleted resources. This will almost always be 1, but in some cases can be 0. See the documentation for individual endpoints for details.

Client errors

The API uses the HTTP error codes 404 Not Found or 400 Bad Request when a correctly authenticated request fails. Authentication errors are covered in the next section. Error responses are also JSON-formatted and include an errors field that can be used for diagnosis:

HTTP/1.1 404 Not Found
Content-Type: application/json

{"errors": "not found"}

The errors field is either a string explanation of the error or an object, in which case the keys are the fields that caused an error and the values are specific messages for that field:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{"code": 100, "errors": {"name": "This field is required.", "layout": "Enter a whole number."}}

Bad Request responses also include a code field with a integer application error code. The codes used are:

100
default error code when none other is applicable
101
duplicate value for something that has to be unique, like creating a dashboard with a name that already exists
102
invalid value for something that only accepts a limited set of values, like a country name or a timezone

The API might also respond with other error codes, like 500 Internal Server Error. This means we messed up, please report it to support@ducksboard.com.

Authentication

All requests are authenticated through HTTP Basic Authentication, using your API key as the username and any password:

curl -v -u APIKEY:x https://app.ducksboard.com/api/dashboards/

You can also use session authentication, which means that while you’re logged in to Ducksboard, you can navigate to https://app.ducksboard.com/api/dashboards/ and you will see the collection of your dashboards.

The API key resources are special and use your Ducksboard username and password instead:

curl -v -u me+ducksboard@example.com:PASSWORD https://app.ducksboard.com/api/api_key

Accessing a resource without correct authentication will generate a 401 Unauthorized HTTP response.

Resource endpoints

Dashboards

Dashboards are the centerpiece, cornerstone and lifeblood of Ducksboard, by which it stands or falls. Or simply: they’re dashboards.

The dashboard fields are:

name string
The displayed dashboard name, its slug must be unique across all of your dashboards.
background string optional
The name of the dashboard’s background, selected from the available backgrounds list. The default background is wood.
layout number
A number used to order the dashboards when displaying them, must be unique across all of your dashboards.
slug string generated
A generated string used to refer to this dashboard in the API. For example, if your dashboard’s name is My Dashboard, the API will generate a slug my-dashboard. The generated slug has to be unique.

Dashboard objects

{
  "name": "my dashboard",
  "background": "wood",
  "layout": 1,
  "slug": "my-dashboard"
}

GET /api/dashboards/

Get a collection of the user’s dashboards, ordered by their layout.

Returns:
{
  "count": 3,
  "data":
          [
            <dashboard object>
          ]
}

GET /api/dashboards/:slug

Get one of the user’s dashboards.

Returns:
<dashboard object>

POST /api/dashboards/

Create a new dashboard. The new dashboard is always ordered to be the last one in the dashboards list, so don’t specify the layout here. The background defaults to wood.

Body:
{
  "name": "my dashboard",
  "background": "dark wood"
}
Returns:
<dashboard object>

PUT /api/dashboards/:slug

Change a dashboard. The dashboard layout and slug must be unique across your dashboards and the dashboards appear in the interface ordered by their layout.

Body:
{
  "name": "new name",
  "background": "grey tiles",
  "layout": 2
}
Returns:
<dashboard object>

DELETE /api/dashboards/:slug

Delete a dashboard. Requests trying to delete a user’s only dashboard will be ignored and return a deleted count of zero.

Returns:
{
  "deleted": 1
}

POST /api/dashboard/:slug/accessed

Update the access time of a dashboard. The last accessed dashboard is the one that gets displayed by default when accessing the application.

Body:
ignored
Returns:
{
  "response": "ok"
}

Access tokens

Access tokens are used to grant read-only access to specific dashboards. Once you generate an access token for a dashboard, you can share it with other people, who can then access the data from that dashboard at https://public.ducksboard.com/:access_token/. You can have as many acces tokens for a dashboard as you want.

Access tokens can optionally be password protected, requiring their users to provide a password each time they access the dashboard’s data using the token.

The access token fields are:

token string generated
The token itself, generated by the API using a cryptographically secure procedure.
description string
A short, descriptive name for the token.
date_created time generated
The date when the token has been created in ISO 8601 format.
password string optional
A password for this token. This field is never returned in responses and is stored using strong one-way encryption.
has_password boolean generated
Is this token be protected by a password?

Access token objects

{
  "token": "ADy16cLy6Q0dp3jomWu5",
  "description": "token for joe",
  "date_created": "2012-03-10T17:20:48.753525+00:00",
  "has_password": false
}

GET /api/dashboards/:slug/tokens/

Get a collection of a dashboard’s access tokens. The tokens are ordered by their creation time, the most recently created one first.

Returns:
{
  "count": 3,
  "data": [
            <token object>
          ]
}

GET /api/dashboards/:slug/tokens/:token

Get one of the dashboard’s access tokens.

Returns:
<token object>

POST /api/dashboards/:slug/tokens/

Create a new access token for the dashboard with the given slug. Omit the password field for no password protection.

Body:
{
  "description": "token for mary",
  "password": "secret!"
}
Returns:
<token object>

DELETE /api/dashboards/:slug/tokens/:token

Delete an access token.

Returns:
{
  "deleted": 1
}

Widgets

Widgets are what displays your data. A widget gets its data from a number of data sources, each data source feeding into a widget’s slot. Think of the widget as a TV set that you hook up with a coaxial cable for image input, a shielded cable for sound and a power cord. The satellite dish and wall socket would be data sources and the connectors at the back of the TV would be slot. Every widget has a number of slots (one or many) and data sources that fit these slots.

../_images/widget-slots-diagram.png

The widget’s configuration is therefore broken down into three parts:

  • widget configuration, such as the widget’s title and position
  • per-slot configuration that decides how data is presented, like the colors and subtitles
  • the content configuration that determines what data is provided to the widget

Widget parameters

The widget configuration always has the same fields:

id number generated
The ID used to refer to this widget in the API. It gets generated by the API automatically.
kind string
Identifies what kind of widget is it, for instance a Twitter search timeline or a Facebook fans counter. The content configuration depends on the widget kind, as obviously a followers widget will need a different set of parameters than a likes counter. Consult the full List of widget kinds for the content parameters of each one.
title string
The widget title, seen in the right upper corner.
dashboard string
A slug of the dashboard name where this widget lives.
sound boolean optional
Does this widget make a sound when new data arrive? Defaults to false.
width and height number optional
The width (as number of columns) and height (as number of rows) of the widget on a dashboard. Each widget kind has a limited set of sizes it can take. Consult the full List of widget kinds for the available sizes of each one.
row and column number optional
The position of the widget on a dashboard. Widgets can have overlapping values for these, or no values at all. The dashboard will then fund a place for the widget and set its row and column attributes.

Slot parameters

Widget slots are numbered, and the slot configuration part is an object where the keys are integers and each value is the configuration of a single slot. Some slots accept more parameters, some none at all. For instance, in a widget with a counter slot you can set its timespan, subtitle and color. In a widget with a timeline slot, there are no slot configuration parameters.

See the widget kinds documentation to check which widget has which slots. The full list of possible slot fields is:

subtitle string
The descriptive text appearing next to the data value. Notapplicable in timelines.
timespan string optional

The time period this slot displays. Only applicable in counters and graphs. Can be one of:

  • daily (last 24 hours)
  • weekly (last 7 days)
  • monthly (last 30 days)

The default is monthly.

color string optional
The color with which data is displayed in HTML notation, eg. #C11F70. Not applicable in timelines.
label string generated
The label of the data source connected to this slot. You never have to provide this value, it will be generated by the API when you create the widget. For widgets accepting custom data, these labels are used to send data using the Push API.

Content parameters

Some widgets require you to first authenticate Ducksboard with an external account, by providing an API key or a username and password. For instance, a New Relic response time counter will need to be linked with a New Relic API account. These widgets will need an account_id parameter in the content section. Other widgets don’t require external authentication, like the RSS timeline widget. For them, you can omit the account_id parameter.

The rest of the parameters depend on the widget kind, consult the List of widget kinds.

account_id number
For widgets that require it, the ID of a previously linked external account.

Widget objects

Here’s an example of a widget that tracks watchers of a project on GitHub. It consists of two slots, a counter and a timeline.

../_images/widget-slots.png
{
  "widget":  {
               "id": 921,
               "kind": "github_watchers_counter_timeline",
               "title": "api example watchers",
               "dashboard": "ducksboard-internal",
               "width": 1,
               "height": 1,
               "row": 1,
               "column": 1,
               "sound": true
             },
  "slots":   {
               "1": {
                      "subtitle" : "watchers",
                      "timespan" : "monthly",
                      "color" : "#C11F70",
                      "label" : "782"
                    },
               "2": {
                    }
             },
  "content": {
               "account_id": 5,
               "user": "ducksboard",
               "repo": "api-examples"
             }
}

GET /api/widgets/

Get a collection of the user’s widgets.

Returns:
{
  "count": 15,
  "data": [
            <widget object>
          ]
}

GET /api/widgets/:id

Get one of the user’s widgets.

Returns:
<widget object>

POST /api/widgets/

Create a new widget. The exact parameters depend on which widget is being created, consult the List of widget kinds for details. width and height default to 1, the row and column default to 1, and sound defaults to false.

Body:
{
  "widget":  {
               "kind": "github_watchers_counter_timeline",
               "title": "api example watchers",
               "dashboard": "ducksboard-internal",
               "width": 1,
               "height": 1,
               "row": 1,
               "column": 1,
               "sound": true
             },
  "slots":   {
               "1": {
                      "subtitle" : "watchers",
                      "timespan" : "monthly",
                      "color" : "#C11F70"
                    }
             },
  "content": {
               "account_id": 5,
               "repo": "api-examples"
             }
}
Returns:
<widget object>

POST /api/widgets/:id/copy

Copy a widget to another dashboard, specified by a slug. A new widget is created, with the same parameters as the copied one. The position is chosen automatically if not specified.

Body:
{
  "dashboard": "my-dashboard"
}
Returns:
<widget object>

PUT /api/widgets/:id

Change a widget. Remember that you can omit any parts of the configuration and only specify the ones you want updated, but you cannot change a widget’s dashboard or kind. Refer to the POST endpoint documentation for a full list of available fields. The returned object has an additional changed field that indicates whether the widget, slots and content configurations changed.

Body:
{
  "widget": {
              "sound": false
            },
  "slots":  {
              "1": {
                     "subtitle": "new users",
                     "label": "signups"
                   }
            }
}
Returns:
{
  "changed": {
               "widget": true,
               "slots": true,
               "content": false
             },
  <widget object>
}

DELETE /api/widgets/:widget_id

Delete a widget.

Returns:
{
  "deleted": 1
}

POST /api/widgets/positions

Update the positions of multiple widgets at once. The object keys are widget IDs. the values should include a row and column field. Both of them default to 1 if not present.

Body:
{
  "7": {
         "row": 1,
         "column": 1
       },
  "9": {
         "row": 1,
         "column": 2
       }
}
Returns:
{
  "response": "ok"
}

GET /api/dashboards/:slug/widgets/

Get a collection of widgets from a dashboard.

Returns:
{
  "count": 5,
  "data": [
            <widget object>
          ]
}

Widget embed tokens

Embed tokens are used to embed widgets on external websites. If widget embedding is enabled, a HTML snippet can be used to create an iframe displaying the requested widget on any site.

Widget embedding is a binary toggle: a widget is either embeddable or not. If embedding is disabled, the previous embed token will stop working and the widget will no longer load on page it has been included in. Each time widget embedding is enabled, a fresh embed token is generated.

The widget embed token fields are:

token string generated
The token itself, generated by the API using a cryptographically secure procedure.
date_created time generated
The date when the token has been created in ISO 8601 format.

Widget embed token objects

{
  "token": "WTy56cLy6R1dp3jomJu6",
  "date_created": "2012-03-10T18:40:48.753525+00:00",
}

GET /api/widgets/:widget_id/embed

Get the current embed token for this widget. If embedding is disabled for this widget, a HTTP 404 response is returned.

Returns:
<token object>

PUT /api/widgets/:widget_id/embed

Enable embedding for this widget and return the embed token. If embedding is already enabled for this widget, return the existing embed token.

Returns:
<token object>

DELETE /api/widgets/:widget_id/embed

Disable embedding for this widget.

Returns:
{
  "deleted": 1
}

Accounts

Accounts are external services that you link Ducksboard with, by providing authentication like the API key or username and password. Once linked, you can use the account to provide data to widgets.

The exact parameters required for each account depend on what kind of service it’s for. For instance to create a New Relic account, you would have to provide the API key, while to link with GitHub you need the OAuth access token. Sometimes you will also need to provide a subdomain, for instance Wufoo creates a companyname.wufoo.com subdomain for each customer.

An account has the following fields:

id number generated
The ID used to refer to this widget in the API. It gets generated by the API automatically.
kind string
Indicates what service this account is for, for instance New Relic or Twitter. The rest of the parameters depend on the account kind. You can consult the full List of account kinds and their parameters below.
username string
The name used to identify the account. In some cases it will be generated for you, for instance Twitter accounts get named with the user’s screen name. For some account kinds you will need to provide a name that will allow you to distinguish that particular account among others. See the documentation on specific account kinds for details. The username has to be unique across accounts of the same kind, but can be repeated in accounts of different kinds.

The rest of the parameters are never returned in API responses and are stored using reversible but strong encryption.

Account objects

{
  "id": 53,
  "kind": "twitter",
  "username": "ducksboard"
}

GET /api/accounts/

Get a collection of the user’s accounts.

Returns:
{
  "count": 8,
  "data": [
            <account object>
          ]
}

GET /api/accounts/:id

Get one of the user’s accounts.

Returns:
<account object>

POST /api/accounts/

Link with a new account. The exact parameters depend on which account is being created. Trying to create an account with a username that already exists will result in an error. While creating an account, basic checks for its correctness are made. If the provided credentials do not allow fetching data from the service, an error is returned.

Body:
{
  "kind": "wufoo",
  "username": "ACME S.A.",
  "subdomain": "acmesa",
  "api_key": "f93s-45md-ksl2-fh8s"
}
Returns:
<account object>

POST /api/accounts/:id

Change an account. The exact parameters depend on which account is being updated. Trying to change the account with a username that already exists will result in an error. While updating an account, basic checks for its correctness are made. If the provided credentials do not allow fetching data from the service, an error is returned.

Body:
{
  "username": "ACME S.A.",
  "subdomain": "acmesa",
  "api_key": "f93s-45md-ksl2-fh8s"
}
Returns:
<account object>

DELETE /api/accounts/:id

Unlink an account. The authentication data stored by Ducksboard are purged and no more data can be fetched from the service.

Warning: This will also remove all widgets using this account!

Returns:
{
  "deleted": 1
}

User

The user resource allows consulting and updating your Ducksboard account.

To change your timezone or country, consult the list of available values below.

Changing your email or password requires providing your current password in the payload, see the documentation below. Your password is never returned in API responses and is stored using strong one-way encryption.

The API key resource accepts HTTP Basic authentication using your Ducksboard username and password and allows you to recover and reset your API key.

User objects

{
  "first_name": "George"
  "last_name": "Duck",
  "email": "george.duck@example.com",
  "timezone": "America/New_York",
  "country": "US",
  "company": "Ducksboard",
  "position": "CEO",
  "plan": "paid"
}

GET /api/user

Get the current user data.

Returns:
<user object>

PUT /api/user

Update user data. Fields that are omitted will keep their previous values. If you want to change your email or send the new_password field, you need to provide the current_password field as well. The returned data will have an extra password_changed field to indicate whether a password change has been made.

Body:
{
  "first_name": "Georgia"
  "last_name": "Duckly",
  "email": "georgia.duckly@example.com",
  "new_password": "supersecret",
  "current_password": "oldpass"
}
Returns:
{
  "password_change": true,
  <user object>
}

GET /api/user/api_key

Get your API key. This endpoint uses HTTP Basic authentication with your Ducksboard username and password.

Returns:
{
  "api_key": "ou6cwknlwsw7twsrshfrbhmnus5r9qlimsb04f73ikey6zo86l"
}

POST /api/user/api_key

Reset your API key. This endpoint uses HTTP Basic authentication with your Ducksboard username and password. The body is ignored and the new API key is returned.

Body:
ignored
Returns:
{
  "api_key": "988vD3LqJmu28O81MDO7ewhghUI71fQePQUqBj5mFARTODksSp"
}