View Backlog Notifications in your Terminal

We primarily use Backlog in our software development process, a web-based project management tool.

For those who love working in terminal emulators, you’ll be glad to know that they have a public API for fetching Backlog data (notifications, issues, projects, etc.). With the API, you can access and update these data from your terminal via cURL or scripting.

You can view the Backlog API documentation here. Basically, you need to be authorized and authenticated first before you can access the desired resources.

For personal use, using API keys would be the ideal way to use the Backlog API.

Authentication via API Key

You can generate an API key from your account settings.

  1. Sign in to your space https://xxx.backlog.com. Your space may have a different domain/url.
  2. Click your avatar icon on the upper right corner of the dashboard to trigger the dropdown menu. Choose Personal Settings → API.
  3. From API Settings screen, add a memo then click Submit to generate an API key.
  4. Copy an API key from your Registered API keys list.
  5. Perform API calls using this key to desired endpoints listed on the official API list.

Example

Backlog URL: https://xxx.backlog.jp
API KEY: mykeycopy1

Where xxx is your Backlog Space key.

Get Space Info

Request

curl "https://xxx.backlog.jp/api/v2/space?apiKey=mykeycopy1"

Response

{
    "spaceKey":"xxx",
    "name":"xxx",
    "ownerId":0000001,
    "lang":"ja",
    "timezone":"Asia/Tokyo",
    "reportSendTime":"09:00:00",
    "textFormattingRule":"markdown",
    "created":"2012-08-03T05:00:27Z",
    "updated":"2017-05-15T06:43:16Z"
}

Notifications

To fetch Backlog notifications, we will use the Get Notification API endpoint.

Description Value
Method GET
URL /api/v2/notifications

Query Parameters

Parameter Type Description
minId Number minimum ID
maxId Number maximum ID
count Number number of records to retrieve(1-100) default=20
order String “asc” or “desc”
senderId Number sender ID

Notification Fetch Script (Ruby)

This time, we will fetch our Backlog notifications through the API using a Ruby script.

Required Gems

Source Code

Save the script below into a file named bklog-notif.rb and update it to suit your needs.

#!/usr/bin/env ruby
require 'json'
require 'rest_client'

class BacklogNotification
  @url
  @data
  REASON = {
    1  => "%s assigned you to an issue.",
    2  => "%s added a comment.",
    3  => "%s added an issue.",
    4  => "%s updated an issue.",
    5  => "%s added a file.",
    6  => "%s added you to a project.",
    9  => "%s did something.",
    10 => "%s assigned you to a pull request.",
    11 => "%s added a comment on a pull request.",
    12 => "%s added a pull request.",
    13 => "%s updated a pull request."
  }

  def initialize(apiKey)
    @url = sprintf("https://xxx.backlog.jp/api/v2/notifications?apiKey=%s", apiKey)
  end

  def fetch(count)
    begin
      @data = JSON.parse(RestClient.get(@url + "&count=#{count}"))
    rescue
      puts "API inaccessible."
      exit(1)
    end
  end

  def getNotifications(count = 20)

    # We can only fetch 1-100 notifications based on API.
    if count < 1 or count > 100
      puts 'Sorry, can only fetch 1-100 notifications.'
      exit(1)
    end

    fetch(count)

    # API call failed.
    if defined?(@data) == nil
      puts "Unable to fetch data."
      exit(1)
    end

    # No notifications to show.
    if @data.length == 0
      return "No notifications."
    end

    # Iterate through all available notifications.
    output = ""
    @data.each do |notification|
      author = notification['sender']['name']
      comment = notification['comment']
      created = notification['created']
      createdFormatted = Time.parse(created).strftime("%F %H:%M")
      issue = notification['issue']
      project = notification['project']
      reasonId = notification['reason']

      projectKey = project && project['projectKey']

      # Add [issuekey -> status] output.
      issueProgress = ""
      if issue != nil
        issueKey = issue && issue['issueKey']
        issueStatus = issue && issue['status']
        issueProgress = sprintf(" [%s → %s]", issueKey, issueStatus['name'])
      end

      # Concat notification output string.
      notificationMessage = notification['alreadyRead'] ? " " : "*"
      notificationMessage += "[#{createdFormatted}] [#{projectKey}] "
      notificationMessage += sprintf(REASON[reasonId], author)
      notificationMessage += issueProgress

      output += notificationMessage + "\n"
    end

    return output
  end
end

# Fetch notifications from Backlog account.
apiKey = "myapikey"
client = BacklogNotification.new(apiKey)
puts client.getNotifications()

Running The Script

Run the Ruby script to fetch notifications.

ruby bklog-notif.rb

Alternatively, you can chmod the file and execute it this way:

chmod +x bklog-notif.rb
./bklog-notif.rb

You can save the script somewhere and add it to your PATH so you could run your script anywhere!

Sample Output

It displays your recent 20 notifications in a human-readable format.

 [2019-06-25 02:31] [NVL] b.lee updated an issue. [NVL-21 → 完了]
 [2019-06-25 02:27] [NVL] b.lee updated an issue. [NVL-22 → 完了]
 [2019-06-21 04:07] [IS] j.chan added a comment. [IS-1 → 完了]
 [2019-06-17 09:54] [NVL] b.lee updated an issue. [NVL-26 → 処理済み]
 [2019-06-17 07:24] [NVL] b.lee added a comment. [NVL-26 → 処理済み]
 [2019-06-17 06:57] [NVL] b.lee updated an issue. [NVL-25 → 完了]
 [2019-06-14 09:59] [NVL] b.lee added an issue. [NVL-26 → 処理済み]
 [2019-06-14 09:26] [NVL] b.lee added an issue. [NVL-25 → 完了]
 [2019-06-14 00:41] [SPF10] j.chan added you to a project.
 [2019-06-13 05:01] [IS] j.chan added you to a project.
 [2019-06-13 01:51] [NVL] b.lee updated an issue. [NVL-19 → 完了]
 [2019-06-10 08:32] [NVL] b.lee updated an issue. [NVL-21 → 完了]
 [2019-06-10 01:58] [NVL] b.lee added an issue. [NVL-22 → 完了]
 [2019-06-07 06:20] [NVL] b.lee added an issue. [NVL-21 → 完了]
 [2019-06-06 11:19] [NVL] b.lee added an issue. [NVL-20 → 完了]
 [2019-05-30 08:36] [ASDF_DEV0] j.chan added a comment. [ASDF_DEV0-378 → 処理済み]
 [2019-05-16 09:02] [ASDF_DEV0] j.chan added a comment. [ASDF_DEV0-378 → 処理済み]
 [2019-05-12 11:10] [ASDF_DEV0] s.jobs updated a pull request.
 [2019-05-12 08:00] [ASDF_DEV0] j.chan updated a pull request.
 [2019-05-09 04:23] [ASDF_DEV0] j.chan updated a pull request.