Harkster API

Version 1.0

Getting Started

https://api.harkster.com/public/v1
REST with access token
1.0

Introduction

Harkster makes it easy to design, organise, and share updates with a team or private audience.

Our public API is built to help you feed external data straight into Harkster.

Authentication

Access to the Harkster API is provided via access tokens which can be configured under settings in the app.

API tokens are tied to a given Harkster user account, using the token you can view and post updates to any channel which the user has access to.

You'll need to provide your access token in the Authorization field of your request header whenever you call the Harkster API.

Wherever you see ACCESS_TOKEN listed in the examples be sure to subsitute your own token.

curl https://api.harkster.com/public/v1/auth \
  -H "Authorization: Bearer ACCESS_TOKEN"

{
    "message": "Authorized",
    "name": "Bert Smith"
}

Limits

Harkster limits the total number of posts an account can publish per month, on the free tier this limit is 100 posts per month.

You can check the number of remaining posts at any time via the account usage endpoint or by observing the following headers in API responses:

Header Description
X-Harkster-Quota Post quota
X-Harkster-Usage Total posts used for the month

If you attempt to publish an update when the quota has been exhausted you will receive a 429 - Too Many Requests response including the following header:

Header Description
X-Harkster-Quota-Reached Contains 'true' if post quota reached

Harkster also rate limits access to the API, if you hit this limit you will receive a 429 - Too Many Requests response, in this case you should wait and try again at a later time.

Working with Data

Terminology

Harkster lets users organise their posts via channels and workspaces.

Channels provide a way to gather posts related to a particular topic, workspaces provide a way to organise around people and provide a home for channels.

Internally Harkster refers to posts as messages, although we do our best not to let internal abstractions leak out to the API you can treat the words message and post interchangably in this context.

Field Types

Harkster posts are created from a collection of fields, each of which has a Type, and may optionally include Label, Data, and Name attributes.

At present the following field types are supported:

Numeric Fields

Type Id Label Data Name Notes
number Y Y Y
currency Y Y Y A number and currency pair, the currency must be provided via the options attribute, e.g. "options": { "ccy": "GBP" }
percentage Y Y Y
counter Y Y Y A whole number

Text Fields

Type Id Label Data Name Notes
text Y Y Y A non-wrapping single line of text
note Y Y Y Multi-line text
bulletPoints Y Y Y Bullet points, each bullet should be separated by a new line character
snippet Y Y Y Multi-line text set in a monospace font

Miscellaneous Fields

Type Id Label Data Name Notes
heading Y - -
divider - - -
date Y Y Y
status Y Y Y Must be null, or one of grey, green, amber, or red
progress Y Y Y Must be a number in the range 0 to 100 inclusive

Posting

When posting new data to Harkster you have two options for creating a post:

  • Generate the updates JSON in your code, then post the update
  • Fetch a pre-existing template, add the relevant data to the returned JSON in your code, then post the update

The first option allows for completely custom updates each time you post, with the trade-off that you must do additional work to generate and validate the JSON you send into Harkster.

The latter option requires less effort to generate the JSON, but relies on pre-existing templates created in the Harkster app, or via the API.

Paging

Some Harkster endpoints return a list of resources, where this is the case the response will include a header called X-Harkster-Continuation which will contain a continuation token.

If this attribute is non-null the server has additonal data available for you, simply call the endpoint again including the token in your request X-Harkster-Continuation header.

Endpoints

Accounts

GET
https://api.harkster.com/public/v1/accounts

Returns a list of accounts the user associated with the provided access token has permission to use.

curl https://api.harkster.com/public/v1/accounts \
  -H "Authorization: Bearer ACCESS_TOKEN"

{    
    {"id": "...", "name": "My Account"},
    {"id": "...", "name": "Acme Inc."},
    {"id": "...", "name": "Computer Club"}    
}
GET {accountId}
https://api.harkster.com/public/v1/accounts/{accountId}

Returns the Id and Name of the provided account.

curl https://api.harkster.com/public/v1/accounts/abc87654321 \
  -H "Authorization: Bearer ACCESS_TOKEN"

{
    "id": "abc87654321",
    "name": "My Account" 
}

Account Usage

GET {accountId}
https://api.harkster.com/public/v1/accounts/{accountId}/usages

Returns the current PostQuota and PostUsage of the provided account.

curl https://api.harkster.com/public/v1/accounts/abc87654321/usages \
  -H "Authorization: Bearer ACCESS_TOKEN"

{
    "postQuota": 100,
    "postUsage": 11
}

Account Workspaces

GET {accountId}
https://api.harkster.com/public/v1/accounts/{accountId}/workspaces

Returns a list of workspaces, belonging to the provided account, that the user associated with the provided access token has permission to use.

curl https://api.harkster.com/public/v1/accounts/abc87654321/workspaces \
  -H "Authorization: Bearer ACCESS_TOKEN"

{    
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "System Alerts"},
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "Financials"},
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "Upcoming Events"}  
}

Workspaces

GET
https://api.harkster.com/public/v1/workspaces

Returns a list of workspaces the user associated with the provided access token has permission to use.

curl https://api.harkster.com/public/v1/workspaces \
  -H "Authorization: Bearer ACCESS_TOKEN"

{    
    {"id": "...", "accountId": "...", "accountName": "My Account", "name": "System Alerts"},
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "Financials"},
    {"id": "...", "accountId": "...", "accountName": "Computer Club", "name": "Upcoming Events"}    
}
GET {workspaceId}
https://api.harkster.com/public/v1/workspaces/{workspaceId}

Returns the Id, AccountId, AccountName and Name of the provided workspace.

curl https://api.harkster.com/public/v1/workspaces/abc87654321
  -H "Authorization: Bearer ACCESS_TOKEN"

{
    "id": "abc87654321",
    "accountId": "rgh23459876",
    "accountName": "Acme Inc.",
    "name": "Project Mercury"
}

Workspace Channels

GET {workspaceId}
https://api.harkster.com/public/v1/workspaces/{workspaceId}/channels

Returns a list of channels, belonging to the provided workspace, that the user associated with the provided access token has permission to use.

curl https://api.harkster.com/public/v1/workspaces/abc87654321/channels \
  -H "Authorization: Bearer ACCESS_TOKEN"

{    
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "Sales Targets", "workspaceId": "...", "workspaceName": "Projects"},
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "Project Status", "workspaceId": "...", "workspaceName": "Projects"},
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "Weekly Check-in", "workspaceId": "...", "workspaceName": "Projects"}    
}

Channels

GET
https://api.harkster.com/public/v1/channels

Returns a list of channels the user associated with the provided access token has permission to use.

curl https://api.harkster.com/public/v1/channels
  -H "Authorization: Bearer ACCESS_TOKEN"

{    
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "Sales Targets", "workspaceId": "...", "workspaceName": "Financials"},
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "Project Status", "workspaceId": "...", "workspaceName": "Projects"},
    {"id": "...", "accountId": "...", "accountName": "Acme Inc.", "name": "Weekly Check-in", "workspaceId": "...", "workspaceName": "Projects"}    
}
GET {channelId}
https://api.harkster.com/public/v1/channels/{channelId}

Returns the Id, Name, AccountId, AccountName, WorkspaceId, and WorkspaceName of the provided channel.

curl https://api.harkster.com/public/v1/channels/zyx12345678 \
  -H "Authorization: Bearer ACCESS_TOKEN"

{
    "id": "zyx12345678",
    "accountId": "rgh23459876",
    "accountName": "Computer Club",
    "name": "Funding Updates",
    "workspaceId": "rgh23459876",
    "workspaceName": "Financials",
}

Channel Templates

GET {channelId}
https://api.harkster.com/public/v1/channels/{channelId}/templates

Returns a list of channel templates the user associated with the provided access token has permission to use.

curl https://api.harkster.com/public/v1/channels/zyx12345678/templates \
  -H "Authorization: Bearer ACCESS_TOKEN"

{    
    {"id": "...", "data": "...", "name": "Sales Targets"},
    {"id": "...", "data": "...", "name": "Project Status"},
    {"id": "...", "data": "...", "name": "Weekly Check-in"}    
}
GET {channelId}, {templateId}
https://api.harkster.com/public/v1/channels/{channelId}/templates/{templateId}

Returns the Id, Name, and Data of the provided channel template.

curl https://api.harkster.com/public/v1/channels/zyx12345678/template/ads876123654
  -H "Authorization: Bearer ACCESS_TOKEN"

{
    "id": "ads876123654",
    "data": {
        "type":"fields",
        "dataset": [
            {"type":"header",id="1","label":"Summary"},
            {"type":"divider",id="2"},
            {"type":"status",id="3","label":"Status","data":null},
            {"type":"progress",id="4","label":"Progress","data":null},
            {"type":"divider",id="5"},
            {"type":"bulletPoints",id="6","label":"Done","data":null},
            {"type":"bulletPoints",id="7","label":"Week Ahead","data":null},
            {"type":"bulletPoints",id="8","label":"Blockers","data":null}
        ]
    }    
    "name": "Project Status"    
}

Posts

GET {channelId}
https://api.harkster.com/public/v1/channels/{channelId}/posts

Returns a list of posts which have been posted to the provided channel.

curl https://api.harkster.com/public/v1/channels/xzx321321321/posts \
  -H "Authorization: Bearer ACCESS_TOKEN"

{    
    {
        "id":"...",           
        "data": {
            "type":"fields",
            "dataset": [
                {"type":"header","id":"1","label":"Summary"},
                {"type":"divider","id":"2"},
                {"type":"status","id":"3","label":"Status","data":"green"},
                {"type":"progress","id":"4","label":"Progress","data":"71"},
                {"type":"divider","id":"5"},
                {"type":"bulletPoints","id":"6","label":"Done","data":"Finished website reboot\nHelped marketing formalise funnel metrics\nCompleted annual review"},
                {"type":"bulletPoints","id":"7","label":"Week Ahead","data":"Returning to app team to help with final push before launch"},
                {"type":"bulletPoints","id":"8","label":"Blockers","data":"Samantha on holiday until Friday\nCould mean data analysis slips a week"}
            ]
        },
        "isDraft":false,
        "name":"Weekly Checkin",        
        "publishedByAt":"2021-02-05T17:23:00.558107+00:00",
        "publishedById": "...",
        "publishedByName":"Jamie"
    },
    {"id":"...", ..., "name":"Weekly Checkin", ...},
    {"id":"...", ...,"name":"Weekly Checkin", ...},
    {"id":"...", ..., "name":"Weekly Checkin", ...},
    {"id":"...", ..., "name":"Announcement", ...},
    {"id":"...", ..., "name":"Weekly Checkin", ...},
    {"id":"...", ..., "name":"Weekly Checkin", ...}    
}
GET {channelId}, {postId}
https://api.harkster.com/public/v1/channels/{channelId}/posts/{postId}

Returns the content of a post which has been posted to the provided channel.

curl https://api.harkster.com/public/v1/channels/zyx12345678/posts/dsf323423453 \
  -H "Authorization: Bearer ACCESS_TOKEN"

{
    "id":"dsf323423453",       
    "data": {
        "type":"fields",
        "dataset": [
            {"type":"header","id":"1","label":"Summary"},
            {"type":"divider","id":"2"},
            {"type":"status","id":"3","label":"Status","data":"green"},
            {"type":"progress","id":"4","label":"Progress","data":"71"},
            {"type":"divider","id":"5"},
            {"type":"bulletPoints","id":"6","label":"Done","data":"Finished website reboot\nHelped marketing formalise funnel metrics\nCompleted annual review"},
            {"type":"bulletPoints","id":"7","label":"Week Ahead","data":"Returning to app team to help with final push before launch"},
            {"type":"bulletPoints","id":"8","label":"Blockers","data":"Samantha on holiday until Friday\nCould mean data analysis slips a week"}
        ]
    },
    "isDraft":false,
    "name":"Weekly Checkin",        
    "publishedByAt":"2021-02-05T17:23:00.558107+00:00",
    "publishedById": "...",
    "publishedByName":"Jamie"
}
POST {channelId}
https://api.harkster.com/public/v1/channels/{channelId}/posts

Creates a new post against the provided channel.

Header Type Requirement Value
Content-Type String Mandatory application/json
Attribute Type Requirement Notes
data Object Mandatory Collection of fields defining the content of the post
isDraft Boolean Optional If true the post is saved to the channel but is not shared with followers, and does not count against the monthly post limit
name String Optional For information purposes only

The data object must take the following form:

{
    "data": {
        "type": "fields",
        "dataset": [
            ... // Your list of fields, with a type, plus label/data as appropriate
        ]
    }
}

NB: The type attribute is reserved for future use, and should always be set to the value fields for version 1.0 of the API.

curl -X POST https://api.harkster.com/public/v1/channels/zyx12345678/posts \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json"
                    
// A post with a single line of text, a status field, and a progress field
{
    "data": {
        "type": "fields",
        "dataset": [
            {
                "type": "text",
                "id": "1",
                "label": "Current Project",
                "data": "Remote Working Playbook"
            },
            {
                "type": "status",
                "id": "2",
                "label": "Current Status",
                "data": "green"
            },
            {
                "type": "progress",
                "id": "3",
                "label": "Overall Progress",
                "data": "42"
            }
        ]
    }
}

NB: Harkster will automatically assign a random Id to a field if none is supplied. The Id allows Harkster to tie the same field together across time, it's therefore important to use the same Id for a given field if you want to benefit from this capability in the future.

PUT {channelId}, {postId}
https://api.harkster.com/public/v1/channels/{channelId}/posts/{postId}

Updates an existing post on the provided channel.

Header Type Requirement Value
Content-Type String Mandatory application/json
Attribute Type Requirement Notes
data Object Mandatory Collection of fields defining the content of the post
isDraft Boolean Optional If true the post is saved to the channel but is not shared with followers, and does not count against the monthly post limit
name String Optional For information purposes only

See the POST method for more details on request content and format.

curl -X PUT https://api.harkster.com/public/v1/channels/zyx12345678/posts/VQde9E10Cy1twJiQNxg \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json"

{
    "data": {
        "type": "fields",
        "dataset": [
            {
                "type": "text",
                "id": "1",
                "label": "Current Project",
                "data": "Remote Working Playbook"
            },
            {
                "type": "status",
                "id": "2",
                "label": "Current Status",
                "data": "green"
            },
            {
                "type": "progress",
                "id": "3",
                "label": "Overall Progress",
                "data": "42"
            }
        ]
    }
}
PUT {channelId}, {postId}
https://api.harkster.com/public/v1/channels/{channelId}/posts/{postId}/publish

Publishes an existing draft post on the provided channel.

curl -X PUT https://api.harkster.com/public/v1/channels/zyx12345678/posts/VQde9E10Cy1twJiQNxg/publish \
  -H "Authorization: Bearer ACCESS_TOKEN"

NB: You will receive a 204 status code to indicate that the post has been published successfully.

DELETE {channelId}, {postId}
https://api.harkster.com/public/v1/channels/{channelId}/posts/{postId}

Deletes an existing post from the provided channel.

Header Type Requirement Value
Content-Type String Mandatory application/json
Attribute Type Requirement Notes
recallMessage Boolean Required If true the post will be removed from follower timelines
curl https://api.harkster.com/public/v1/channels/zyx12345678/posts/VQde9E10Cy1twJiQNxg \
  -X DELETE \
  -H "Authorization: Bearer ACCESS_TOKEN"
  -H "Content-Type: application/json" \
 --data '{ "recallMessage": true }'

NB: You will receive a 204 status code to indicate that the post has been successfully deleted.