Ducksboard

Push API

Overview

The Push API allows sending your own data to Ducksboard. A special custom family of widgets can be used to display data sent that way.

The API uses HTTPS exclusively and accepts JSON payloads. Access to the Push API is through push.ducksboard.com.

If you want to quickly jump into the action, read the Tutorial that should get you started.

An example request is:

curl -v -u YOUR_API_KEY:unused -d '{"value": 10}' https://push.ducksboard.com/values/235

Data model

Each call to the Push API stores one or more value for a single data source, identified by a label. You can find the labels for data sources through the Dashboard API or by looking at the URLs tab in the custom widget configuration dialog.

Only data sources from custom widgets can accept data over the Push API. Other data sources get their data automatically from Ducksboard itself and will not accept values from the Push API.

The format of data accepted by the Push API depends on which kind of widget will display the sent values. See below for a summary of all of the acceptable formats.

Push values format

Numbers

Simple floating point numbers, for instance:

{
  "value": 3.5
}

Increments from previous values:

{
  "delta": 1.5
}

Gauges

Floating point numbers from between 0.0 and 1.0, interpreted as percentages, for instance 0.25 means 25%.

{
  "value": 0.25
}

Timeline objects

Objects composed from a title, content and image URL and an optional link for the timeline item.

{
  "value": {
             "title": "error message",
             "image": "http://assets.example.org/error.png",
             "content": "All system stop!",
             "link": "http://monitoring.example.org/incident/354"
           }
}

Image objects

Objects composed from the image URL and a caption text.

{
  "value": {
             "source": "http://assets.example.org/logo.png",
             "caption": "Example Corp, Inc."
           }
}

Text objects

Objects composed from the text content.

{
  "value": {
             "content": "Text!\nLorem ipsum dolor sit amet...",
           }
}

Leaderboard objects

Objects composed from list of items, each item composed from a name and a list of values.

{
   "value": {
          "board": [
                  {"name": "Abdul-Jabbar", "values": [38387, 1560, 24.6]},
                  {"name": "Karl Malone", "values": [36928, 1476, 25.0]},
                  {"name": "Michael Jordan", "values": [32292, 1072, 30.1]},
                  {"name": "W. Chamberlain", "values": [31419, 1045, 30.1]},
                  {"name": "Kobe Bryant", "values": [29484, 1161, 25.4]},
                  {"name": "Shaq O Neal", "values": [28596, 1207, 23.7]},
                  {"name": "Moses Malone", "values": [27409, 1329, 20.6]},
                  {"name": "Elvis Hayes", "values": [28313, 1303, 21.0]},
                  {"name": "H. Olajuwon", "values": [26946, 1238, 21.8]}
                  ]
            }
}

Trend Leaderboard objects

Identical to leaderboard objects, but each item can have an extra “trend” field set to either “up”, “down” or “equal” to override automatic trend calculation.

You can find more info in the documentation for Trend Leaderboards.

{
   "value": {
          "board": [
                  {"name": "value1", "values": [1560, 24.6]},
                  {"name": "value2", "values": [1560, 24.6]},
                  {"name": "value3", "values": [1560, 24.6]},
                  {"name": "overridden", "values": [1560, 24.6], "trend": "up"}
                  ]
            }
}

Status Leaderboard objects

Identical to leaderboards objects, but each item has to have an extra “status” field set to either “green”, “yellow”, “red” or “gray” (“grey” is also accepted).

You can find more info in the documentation for Status Leaderboards.

{
   "value": {
          "board": [
                  {"name": "everything fine", "values": ["100%"], "status": "green"},
                  {"name": "warning, warning", "values": ["80%"], "status": "yellow"},
                  {"name": "very bad", "values": ["15%"], "status": "red"},
                  {"name": "not sure", "values": ["--"], "status": "gray"}
                  ]
            }
}

Funnel objects

Objects composed from list of items, each item composed from a name and a value.

You can find more info in the documentation for Funnels.

{
   "value": {
          "funnel": [
                  {"name": "STEP 1", "value": 1600},
                  {"name": "STEP 2", "value": 1400},
                  {"name": "STEP 3", "value": 1200},
                  {"name": "STEP 4", "value": 900},
                  {"name": "STEP 5", "value": 600},
                  {"name": "STEP 6", "value": 330}
                  ]
            }
}

Completion objects

Objects composed from a minimum value, a maximum value and the current value.

You can find more info in the documentation for Completion.

{
  "value": {
         "current": 19790,
         "min": 0,
         "max": 25000
         }
}

Using pull

Every data source that can be pushed into can also be configured to pull data from a user-defined URL. When you set a pull URL on a custom widget’s data source, Ducksboard will repeatedly poll that URL and interpret data returned from it just like it would have been pushed.

As an example, if you create a custom Counter widget and configure its pull URL to be https://example.org/app/report/pull.json Ducksboard will make a request to that URL and expect ro receive data in a format used by the Push API, for instance {"value": 10}. For more information about data format used by the Push API, see Request format.

It is possible to mix pull and push for the same data source, but it is disencouraged. Error detection and deduplication might get confused if you mix push and pull data in the same data source.

If a data source’s pull URL is changed, previous data from that data source will be discarded. This design choice is to avoid mixing data from different URLs, which could result in misleading graphics being displayed.

If you’d like to change a pull URL and keep the data, it’s best to dump it first using the Pull API and push it back after the URL has been changed.

Deduplication

Timelines are a bit more difficult to work with when using pull URLs, because each time Ducksboard obtains a message object from your pull URL, it will get interpreted as a new item to be put on the timeline.

To make using timelines with pull URLs easier, Ducksboard looks for an id field in the received objects and discards those whose IDs were already seen.

For example, if three consecutive polls from a timeline would receive these three responses:

{"value": {"id": 132, "title": "OK", "content": "All systems go"}}

{"value": {"id": 132, "title": "OK", "content": "All systems go"}}

{"value": {"id": 133, "title": "ERROR", "content": "Errors!"}}

Only two messages would appear on the timeline, whereas consecutively pushing these messages to push.ducksboard.com would result in three separate items showing up on the timeline.

HTTP methods

The Push API supports two HTTP methods: POST and DELETE.

POST requests
Send new data for a given data source to Ducksboard. You can either send a single value or a list of values. Each value might have a timestamp associated. See the documentation for available resources for details.
DELETE requests
Delete data from a given data source. After receiving a DELETE request, all data stored by that data source is removed. Use this to clean up test data or to reset the state of a data source before loading a fresh set of values.

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 might include an errors field with simple diagnostic information:

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

{"errors": "malformed request"}

If the data you sent exceeds an internal limit, a 413 Request Entity Too Large error code will be returned. Internal limits are subject to change, but no reasonable application should ever run into them. If you’re getting these errors and would like the limits to be lifted for you, please contact us.

You might get other error codes as well, like 500 Internal Server Error. This means we did something wrong, please report it to support@ducksboard.com.

Authentication

All requests are authenticated using HTTP Basic Authentication, with your API key being the username. The password is ignored:

curl -v -u YOUR_API_KEY:unused -d '{"value": 1}' https://push.ducksboard.com/values/805

Accessing a resource with an invalid API key will generate a 401 Unauthorized HTTP response. Using the API key of a user that does not have permissions to access a particular resource will generate a 403 Forbidden HTTP response. For instance, if using an invalid key:

curl -v -u invalidapikey:x -d '{"value": 1}' https://push.ducksboard.com/values/805

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Ducksboard push API"

But if using a correct key, but trying to access data source 1000, which does not belong to the authenticated user:

curl -v -u correctkey:x -d '{"value": 1}' https://push.ducksboard.com/values/1000

HTTP/1.1 403 Forbidden

Resource endpoints

values

The values endpoint allows you to send values to a single data source, specified by its label. For brevity, the values resource can be accessed through a /v/ shorthand. The following are equivalent:

https://push.ducksboard.com/values/15234
https://push.ducksboard.com/v/15234

POST /values/:label

Send a value or a list of values. Each value can have a timestamp associated with it. Timestamps should be UNIX timestamps in seconds, expressed as numbers with an optional fractional part. If no timestamp is specified, the value is assumed to be timestamped with the current time.

Values can be absolute or deltas. Delta values cannot appear in lists and their timestamps are ignored, they are always treated as differences from the current value.

Single value:
{
  "value": <number or object>
}
Delta value:
{
  "delta": <number>
}
Single value with timestamp:
{
  "timestamp": 1332971928.20006,
  "value": <number or object>
}
Multiple values:
[
  {
    "value": <number or object>
  }
]
Multiple values with timestamps:
[
  {
    "timestamp": 1332971928.20006,
    "value": <number or object>
  }
]
Returns:
{
  "response": "ok"
}

POST /values/

Send values to multiple data sources in bulk. This endpoint allows updating several widgets (or several slots of the same widget) with a single query.

The payload should be an object with keys corresponding to slot labels and values being the same objects described in the single-label case.

Similar to the single-label case, lists of values can also be used, to send multiple values to multiple labels at the same time.

This endpoint always returns 200 OK, even if errors are detected for some values. Individual error codes can be found in the response payload, one per label specified in input.

Note that this operation is not atomic! A 200 code for a label meas it has been updated, other codes mean that the update did not take place for that particular label.

Multiple labels:
{
  "<label 1>": <number or object>,
  "<label 2>": <number or object>
}
Multiple labels, single or multiple values per label:
{
  "<label 1>": [
                 {
                   "timestamp": 1332971928.20006,
                   "value": <number or object>
                 },
                 {
                   "timestamp": 1332972928.30020,
                   "value": <number or object>
                 }
               ]
  "<label 2>": <number or object>
}
Returns:
{
  "<label 1>": {
                 "code": 200,
                 "response": "ok"
               },
  "<label 2>": {
                 "code": 400,
                 "errors": "value needs to be a number"
               }
}

DELETE /values/:label

Delete all data for a given data source. The request body is ignored.

Returns:
{
  "response": "ok"
}

DELETE /values/

Deletes all data for multiple data sources in bulk. The request body should contain a list of labels.

Similar to POST, this endpoint always returns 200 OK, even if errors are detected. Individual error codes can be found in the response payload.

List of labels:
[
  "<label 1>",
  "<label 2>"
]
Returns:
{
  "<label 1>": {
                 "code": 200,
                 "response": "ok"
               },
  "<label 2>": {
                 "code": 401,
                 "errors": "forbidden"
               }
}