Vimaly REST API version 2 documentation

This is the reference documentation for Vimaly's REST interface version 2. Version 2 is backwards compatible with version 1.

Table of contents

  1. Overview of REST requests
    1. Schema
    2. Authentication
    3. Compression options
    4. Format of PUT body
    5. Errors
  2. Resources
    1. /ids
    2. /users
    3. /user-groups
    4. /custom-fields
    5. /ticket-types
    6. /boards
    7. /bins
    8. /tickets
    9. /ticket-search
    10. /ticket-attachments
    11. /ticket-comments
    12. /webhooks
  3. User group access levels

Overview of REST requests

To use the interface you need a Vimaly user login or an API authentication key (auth-key). For full access you need a login or auth-key with admin rights for the organization you will be using. An auth-key can be generated from Settings at Organizations→[Org name]→General.

Schema

The access url is of the form:

<rest-prefix>/<resource>/<reference>?<control-parameters>
          
Where:

The header field X-Vimaly-No-Feedback may also be set to a comma separated list (no spaces) of webhook ids. This will stop the specified webhooks from actions any events triggered by this action.

Responses are in the form of http status codes and JSON data in utf-8.

Authentication

An auth-key can be generated by an admin user in Settings at Organizations→[Org name]→General

To use an API authentication key, either put it in Authorization header (Authorization: bearer yourAuthKey) or append it in the query parameter (auth-key=yourAuthKey)

Alternatively basic authentication can used to access the resources by supplying the email (lower-case) and password.

Examples

Curl example using API auth-key (sent in a header):

curl -H 'Authorization: bearer ds62GDS4ds423DF24:432D45s2324d3hf7fdD7weFD' https://h0123.vimaly.com/rest/2/trnkz/users

=> SUCCESS [200] (application/json)
[{
  "_id":"aghg8HKi2rzMzygiW",
  "name":"Russell Healy",
  "email":"russell@vimaly.com",
  "initials":"RH"
},{
  "_id":"juFEJpcvmbHiAZYuD",
  "name":"Geoff Jacobsen",
  "email":"geoff@vimaly.com",
  "initials":"GJ"
}]
          

Curl example using API auth-key (sent as parameter):

curl https://h0123.vimaly.com/rest/2/trnkz/users?auth-key=ds62GDS4ds423DF24:432D45s2324d3hf7fdD7weFD

=> SUCCESS [200] (application/json)
[...]
          

Wget example using email and password:

wget --http-user=geoff@vimaly.com --http-password=secret \
https://h0123.vimaly.com/rest/2/trnkz/users
=> SUCCESS [200] (application/json)
[...]
          

Compression options

Gzip compression can be used for the request body for both requests and responses. Use the header Accept-Encoding: gzip to receive a compressed response body (if applicable) and Content-Encoding: gzip to send a compressed request body.

example

curl -X POST --data-binary @path/to/my-json-body.gz -H "Content-Type: application/json" \
  -H "Content-Encoding: gzip" --compressed
https://sd1.vimaly.com/rest/2/demo/tickets/DwPkagsKnisNbnmhb
        

Format of PUT request body

The PUT request body can update parts of fields in a section called $partial. The format of the $partial sections is:
{
  topLevelField1: [
    cmdOrSubField1, value,
    cmdOrSubField2, value,
    ...
  ],
  topLevelField2: [...],
  ...
}
        
where topLevelFieldn is the name of a top-level field such as: name or checklists and where cmdOrSubFieldn can be a sub-level field such as: checklistId123.items.itemId456.name, customFieldId123; or one of the commands:

Errors

Errors are have a status code in the 400 range and consist of either a plain text message of a JSON data body.

The format of an JSON error is {"<field>": [<reason>,...]} where:

Resources

Resource names start after the <rest-prefix> (see above).

/ids

When new records are created unique ids must be supplied by the caller. This is so that the POST commands can be resent multiple times without creating multiple records.

This command supplies the client with a list of suitable ids to use. Only accepts the max-results query parameter.

Methods

GET /ids?max-results=<n>

Return a list of ids

parameterdescription
max-results (optional)The number of ids to return; must be between 1 and 100. Defaults to 4.

response

200 - application/json

example

get /ids?max-results=3

["QQa28StuRkeSiBPBR","oHhqwoMCgJLa2SCam","ig22QAox8Q3MiuSEq"]
          

/users

Retrieve details about users and invite users.

Methods

GET /users/<_id or email>

Return details for specified user

parameterdescription
_idThe user's id
emailThe user's email address

response

200 - application/json

404 - Not found

example

get /users/aghg8HKi2rzMzygiW

{
  "_id":"aghg8HKi2rzMzygiW",
  "name":"Russell Healy",
  "email":"russell@vimaly.com",
  "initials":"RH",
  "userGroups":["zygiWaghg8HKi2rzM", "Ki2rzMzygiWaghg8H"]
}
          

GET /users

Return list of users for the organization.

response

200 - application/json

example

get /users

[{
  "_id":"aghg8HKi2rzMzygiW",
  "name":"Russell Healy",
  "email":"russell@vimaly.com",
  "initials":"RH"
},{
  "_id":"juFEJpcvmbHiAZYuD",
  "name":"Geoff Jacobsen",
  "email":"geoff@vimaly.com",
  "initials":"GJ"
}]
          

POST /invite-user

Invite a user to join the organization. Sends email invitation to user, and returns the user's attributes. Fields are sent as a JSON body.

fielddescription
email (required)The user's email address
name (required)The user's name
initials (required)The user's initials. Maximum three letters
userGroupsA list of ids for userGroups that the user should be a member of

response

200 - application/json

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

example

post /invite-user

JSON body:

{
  "name": "Jane Doe",
  "email": "jane@vimaly.com",
  "initials": "JD",
  "userGroups": ["UiRfyntfEe6Su8JiH"]
}

Response:

{
    "_id": "xwT1PEzim7JxGy181",
    "email": "jane@vimaly.com",
    "name": "Jane Doe",
    "initials": "JD",
    "userGroups": [
        "UiRfyntfEe6Su8JiH"
    ]
}
          

/user-groups

Retrieve details about user groups.

Methods

GET /user-groups/<_id>

Return details for specified user group

parameterdescription
_idThe user group id

response

200 - application/json

404 - Not found

owner_ids and manager_ids are lists of user-ids that own or can manage the user-group.

example

get /user-groups/PGNCrjE4oyjXvzi2h

{
  "_id":"PGNCrjE4oyjXvzi2h",
  "name":"Designers",
  "createBoard":true,
  "owner_ids":["aghg8HKi2rzMzygiW"],
  "manager_ids":["juFEJpcvmbHiAZYuD"]
}
          

GET /user-groups

Return list of user groups for the organization

response

200 - application/json

example

get /user-groups

[{
  "_id":"PGNCrjE4oyjXvzi2h",
  "name":"Designers",
  "createBoard":true,
  "owner_ids":["aghg8HKi2rzMzygiW"],
  "manager_ids":["juFEJpcvmbHiAZYuD"]
}, {
  "_id":"gJ3wQ0iuuPbmKlRsY",
  "name":"Testers",
  "createBoard":false,
  "owner_ids":["juFEJpcvmbHiAZYuD"]
}]
          

/custom-fields

Retrieve details about custom fields.

Methods

GET /custom-fields/<_id>

Return details for specified custom field

parameterdescription
_idThe custom field id

response

200 - application/json

404 - Not found

type is: 1: text, 2: decimal, 3: integer, 4: list

example

get /custom-fields/PGNCrjE4oyjXvzi2h

{
  "_id":"d8UWxfg398Kfss0P2D",
  "name":"Complexity",
  "type":3
}
          

GET /custom-fields

Return list of custom fields for the organization

response

200 - application/json

type is: 1: text, 2: decimal, 3: integer, 4: list

example

get /custom-fields
[{
  "_id":"PGNCrjE4oyjXvzi2h",
  "name":"Complexity",
  "type":3
}, {
  "_id":"rt2Rj66Y9fTT7xHZx",
  "name":"Close reason",
  "type":4,
  "options":[{
    "id":1,
    "name":"Fixed",
    "order":128
  }, {
    "id":2,
    "name":"Duplicate",
    "order":256,
    "disabled":true
  }, {
    "id":3,
    "name":"Wont Fix",
    "order":384
  }]}
]
          

/ticket-types

Retrieve details about ticket types.

Methods

GET /ticket-types/<_id>

Return details for specified ticket type

parameterdescription
_idThe ticket type id

response

200 - application/json

fielddescription
colorThe background color for tickets of this type
disabled (optional)This ticket type should not be used for creating new tickets
<standard-field> (optional) A standard-field is any of the following:
  • estimatedDuration (value type: interval)
  • estimatedEffort (value type: effort)
  • estimatedEffortRemaining (value type: effort)
  • estimatedCost (value type: currency)
  • actualCost (value type: currency)
  • plannedStartDate (value type: date)
  • actualStartDate (value type: date)
  • dueDate (value type: date)
  • completedDate (value type: date)
and has a value of either "optional" or "alwaysShow" where "alwaysShow" indicates that the ticket view in the user interface should always display the field regardless of whether the field has a value or not, and where "optional" indicates that the field is only displayed if it has a value.

The types effort and currency have additional fields:

  • effort has a "units" field like estimatedEffortUnits and estimatedEffortRemainingUnits and can be either "points" or "interval".
  • currency has a "currency" field like estimatedCostCurrency and actualCostCurrency. Currencies are ISO 4217 three letter codes like USD and EUR

customFields (optional)Map of the custom fields available for this ticket type
customFields.<_id>The id of a custom field
customFields.<_id>.orderThe order to present this custom field in a list
customFields.<_id>.alwaysShowCustom field is shown on all tickets of this ticket type

404 - Not found

example

get /ticket-types/omCx7PZMAbZxFSf3a

{
  "_id":"omCx7PZMAbZxFSf3a",
  "name":"Defect",
  "color":"#88ffff",
  "estimatedEffort": "optional",
  "estimatedEffortUnits": "interval",
  "actualCost":"alwaysShow",
  "actualCostCurrency":"NZD",
  "customFields":{
    "zAFA7t32HcyLYkzn8":{
      "order":-320
    },"EvSCsej8qJeQHLJo4":{
      "order":576,"alwaysShow":true
    },"nMGsF638LdArbKBiW":{
      "order":704
    }
  }
}
          

GET /ticket-types

Return list of ticket types for the organization

response

200 - application/json

example

get /ticket-types
[{
  "_id":"SaJKSZDwpHfTuKb93",
  "name":"Enhancement",
  "color":"#88ffff",
  "customFields":{
    "EMWS9CpZnJc4Ei256":{
      "order":128
    }
  }
},{
  "_id":"omCx7PZMAbZxFSf3a",
  "name":"Defect",
  "color":"#ffff88",
  "customFields":{
    "zAFA7t32HcyLYkzn8":{
      "order":-320
    },"EvSCsej8qJeQHLJo4":{
      "order":576,"alwaysShow":true
    },"nMGsF638LdArbKBiW":{
      "order":704
    }
  }
}]
          

/boards

Retrieve details about boards.

Methods

GET /boards/<_id>

Return details for specified board

parameterdescription
_idThe board id

response

200 - application/json

fielddescription
nameThe name of the board
userGroupsA list of user-group access levels
colorThe background color of the board
width, heightThe dimensions of the board
binsA list of the bin-ids for bins on the board
_versionThe version number of the board. Increased when a new version of the board is published.

404 - Not found

example

get /boards/p7qVHmQZhYhQEIo2t

{
  "_id": "p7qVHmQZhYhQEIo2t",
  "_version": 2,
  "name": "Issue Triage",
  "userGroups": [{
    "al": 400,
    "id": "UiRfyntfEe6Su8JiH"
  }],
  "color": "#666666",
  "width": 1950,
  "height": 1145,
  "updatedAt": "2017-05-29T00:57:45.676Z",
  "bins": [
    "aajmQbUOXGg5RtA67",
    "icjI6J9bx3XiCwzAV",
    "ACwza47jMQOF8fnkn"
  ]
}
          

GET /boards

Return list of boards for the organization

response

200 - application/json

example

get /boards

[{
  "_id": "p7qVHmQZhYhQEIo2t",
  "_version": 2,
  "name": "Issue Triage",
  "userGroups": [{
    "al": 400,
    "id": "UiRfyntfEe6Su8JiH"
  }],
  "color": "#666666",
  "width": 1950,
  "height": 1145,
  "updatedAt": "2017-05-29T00:57:45.676Z",
  "bins": [
    "aajmQbUOXGg5RtA67",
    "icjI6J9bx3XiCwzAV",
    "ACwza47jMQOF8fnkn"
  ]
},{
  "_id": "8qVUkRqt80ATIHEV4",
  "_version": 4,
  "name": "Risks and Issues",
  "userGroups": [{
    "al": 400,
    "id": "UiRfyntfEe6Su8JiH"
  }],
  "color": "#666666",
  "width": 2250,
  "height": 1322,
  "updatedAt": "2017-05-29T00:57:45.676Z",
  "bins": [
    "cLhyI7WhqBErHxSZY",
    "b5WnIl3K4kbQLIHaN",
    "nE1SfsY0jFucxpWai",
    "A972BfsUXhEBZfYLg",
    "N5MmRuQXLAF4iiZxI"
  ]
}]
          

/bins

Create, update and inquire about bins.

Methods

GET /bins/<_id>

Return details for specified bin

parameterdescription
_idThe bin id

response

200 - application/json

fielddescription
nameThe name of the bin
userGroupsA list of user-group access levels
colorThe background color of the bin
wipLimit (optional)Maximum number of tickets in this bin until a warning shows

404 - Not found

example

get /bins/wi8NwSQqEB3bYp9Jr

{
  "_id":"wi8NwSQqEB3bYp9Jr",
  "name":"ops.exp.Expedite Issues Queue",
  "color":"#ffffff",
  "wipLimit":4,
  "userGroups": [{
    "al": 400,
    "id": "UiRfyntfEe6Su8JiH"
  }]
}
          

GET /bins

Return list of bins for the organization

response

200 - application/json

example

get /bins

[{
  "_id":"6eAwSbzp2EXjBk42b",
  "name":"ops.exp.Done",
  "color":"#b3b3b3",
  "userGroups": [{
    "al": 400,
    "id": "UiRfyntfEe6Su8JiH"
  }]
},{
  "_id":"wi8NwSQqEB3bYp9Jr",
  "name":"ops.exp.Expedite Issues Queue",
  "color":"#ffffff",
  "wipLimit":4,
  "userGroups": [{
    "al": 400,
    "id": "UiRfyntfEe6Su8JiH"
  }]
}]
          

PUT /bins/<_id>

Update details for specified bin. Fields are sent as a JSON body. Only specify the fields to be changed.

parameterdescription
_idThe bin id
fielddescriptionexample
nameThe unique name of the bin
userGroupsA list of user-group access levels
color The background color of the bin. Format: #xxxxxx where x is a hex digit 0-9,a-f
wipLimit (optional)Maximum number of tickets in this bin until a warning shows

response

204 - No content - update was successful

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

404 - Not found

POST /bins/<_id>

Create a bin with the specified fields. Fields are sent as a JSON body.

parameterdescription
_idA unique id for the bin
fielddescription
name (required)The unique name of the bin
userGroupsA list of user-group access levels
color The background color of the bin. Format: #xxxxxx where x is a hex digit 0-9,a-f
wipLimit (optional)Maximum number of tickets in this bin until a warning shows

response

204 - No content - Creation was successful

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

400 - application/json {_id: [["is_invalid"], ["already_exists"], ["not_unique"]]} already_exists indicates a bin already has this id

/tickets

Create, update, delete and inquire about tickets.

Methods

GET /tickets/<_id>?rtformat=text|html

Return details for specified ticket

parameterdescription
_idThe ticket id
rtformatIf set to "html" returns the ticket description as html markup

response

200 - application/json

fielddescription
bin_idThe id for the bin the ticket is in.
ticketType_idThe id for the ticket-type of this ticket
enclosed_idThe id for the parent of this ticket is enclosed in (if any)
orderThe position of the ticket within the bin
assigned_idsList of user ids assigned to this ticket
watch_idsList of user ids watching this ticket
<standard-field> Any or all of the standard fields (see Ticket types for a definition). Depending on a field's type it has the following format:
typeformat
"interval" (or "effort" with unit of "interval") [<number>, <unit>] where <unit> is one of "mins", "hrs", "days", "wks"
"effort" (with unit of "points") [<number>, "pts"]
"curency" [<decimal>, <currency>] where <decimal> is a string of digits with an optional decimal point and <currency> corresponds to the standard-field's currency from the ticket's ticket-type
"date" "yyyy-mm-ddThh:mm:ss.sssZ"; a string of the date in ISO format. The time portion of the date will differ depending what time zone the date is relative to; for example NZST would have "T12:00:00.000Z" appended to the date.
checklists (optional)A map of checklists
checklists.<cl_id>A checklist. cl_id should be unique
checklists.<cl_id>.itemsA map of items for the checklist
checklists.<cl_id>.items.<item_id>The id for the item
checklists.<cl_id>.items.<item_id>.checkedPresent and true if the item is complete
customFields (optional)A map of custom fields
customFields.<cf_id>The value of a custom field. The cf_id determines which custom-field. The value is determined using the custom field's type

404 - Not found

example

get /tickets/bnmhbDwPkagsKnisN
{
  "_id":"bnmhbDwPkagsKnisN",
  "name":"Select a group of bins",
  "updatedAt":"2017-07-23T04:50:05.123Z",
  "bin_id":"9P3ubgAqygpr2kmKW",
  "ticketType_id":"XxcXo2NQq3sHcuMfW",
  "order":128,
  "estimatedDuration":[3, "days"],
  "estimatedEffort":[2.5, "pts"],
  "actualCost":["123.45", "EUR"],
  "plannedStartDate":"2015-12-31",
  "checklists":{
    "gget6HRPhy65gg95d":{
      "name":"Acceptance tests",
      "order":100,
      "items":{
        "QpqssantGFinDP4Y5":{
          "name":"Can use ctrl-click to add to selection",
          "order":100,
        },
        "g9dekhFwsZxiTcAwR":{
          "name":"Can move bins together",
          "order":200,
          "checked":true
        }
      }
    }
  },
  "customFields":{
    "QaGQsdXHZkiRBMfom": 2,
    "HHzNciedfaRmaymng": "E123TWS"
    "myngj843jfGHzNcda": "2017-07-23T12:00:00.000Z"
  }
}
          

GET /tickets?bin_id=<bin_id>

Return list of tickets for the specified bin_id

response

200 - application/json

400 - application/json {bin_id: [["is_required"], ["is_invalid"]]} - or access not allowed

example

get /tickets?bin_id=9P3ubgAqygpr2kmKW
[{"_id":"LWWRDuSZrjzxqW7fL",
  "name":"Widgets are broken",
  "updatedAt":"2017-07-23T04:50:05.123Z",
  "bin_id":"9P3ubgAqygpr2kmKW",
  "ticketType_id":"XxcXo2NQq3sHcuMfW",
  "order":64
 },{
  "_id":"bnmhbDwPkagsKnisN",
  "name":"Select a group of bins",
  "updatedAt":"2017-07-23T04:50:05.123Z",
  "bin_id":"9P3ubgAqygpr2kmKW",
  "ticketType_id":"XxcXo2NQq3sHcuMfW",
  "order":128,
  "checklists":{
    "gget6HRPhy65gg95d":{
      "name":"Acceptance tests",
      "order":100,
      "items":{
        "QpqssantGFinDP4Y5":{
          "name":"Can use ctrl-click to add to selection",
          "order":100,
        },
        "g9dekhFwsZxiTcAwR":{
          "name":"Can move bins together",
          "order":200,
          "checked":true
        }
      }
    }
  },
  "customFields":{
    "QaGQsdXHZkiRBMfom": 2
    "HHzNciedfaRmaymng": "E123TWS"
  }
}]
          

GET /tickets?parent_id=<parent_id>

Return list of child tickets for the specified parent_id

response

200 - application/json

400 - application/json {parent_id: [["is_required"], ["is_invalid"]]} - or access not allowed

example

get /tickets?parent_id=qygpr2kmKW9P3ubgA
[{"_id":"LWWRDuSZrjzxqW7fL",
  "name":"Child 1",
  "updatedAt":"2017-07-23T04:50:05.123Z",
  "bin_id":"9P3ubgAqygpr2kmKW",
  "ticketType_id":"XxcXo2NQq3sHcuMfW",
  "order":64
 },{
  "_id":"bnmhbDwPkags",
  "name":"Child 2",
  "updatedAt":"2017-07-23T04:50:05.123Z",
  "bin_id":"KnisN2kmKW9P3ubgA",
  "ticketType_id":"XxcXo2NQq3sHcuMfW",
  "order":128
}]
          

GET /tickets?child_id=<child_id>

Return list of parent tickets for the specified child_id

response

200 - application/json

400 - application/json {child_id: [["is_required"], ["is_invalid"]]} - or access not allowed

example

get /tickets?child_id=qygpr2kmKW9P3ubgA
[{"_id":"SZrjzxqW7fLLWWRDu",
  "name":"Parent 1",
  "updatedAt":"2017-07-23T04:50:05.123Z",
  "bin_id":"9P3ubgAqygpr2kmKW",
  "ticketType_id":"XxcXo2NQq3sHcuMfW",
  "order":64
 },{
  "_id":"mhbDwPkagsbn",
  "name":"Parent 2",
  "updatedAt":"2017-07-23T04:50:05.123Z",
  "bin_id":"KnisN2kmKW9P3ubgA",
  "ticketType_id":"XxcXo2NQq3sHcuMfW",
  "order":128
}]
          

PUT /tickets/<_id>

Update details for specified ticket. Fields are sent as a JSON body. Only specify the fields to be changed.

parameterdescription
_idThe ticket id
fielddescriptionexample
nameThe name of the ticket
rtformatThe description is 'text' or in 'html' markup format
descriptionThe description for the ticket
bin_idThe id for the bin the ticket is in.
ticketType_idThe id for the ticket-type of this ticket
orderThe position of the ticket within the bin
assigned_idsAssign or unassign a user on this ticket using the user's id
{"$partial": {"assigned_ids": [
  '$add', 'OBodk3LR30UgW8tyL'
]}}
                
watch_idsAdd or remove user as a watcher of this ticket using their id
{$partial: {watch_ids: [
  '$remove', 'OBodk3LR30UgW8tyL'
]}}
                
<standard-field>See get ticket
customFieldsSee get ticket
{"$partial": {"customFields": [
  // change customField
  "PGNCrjE4oyjXvzi2h", 1234
]}}
                
checklistsAdd, remove, or update a checklist or checklist-item
{"$partial": {"checklists": [
  // add checklist
  "uBw3JKT76oFmL8guK", {
    "name": "Checklist name", "order": 100
  },
  // change checklist name
  "w8lpvGxgi5yP1T6CE.name", "new name",
  // add checklist item
  "w8lpvGxgi5yP1T6CE.items.FcYCgh8PSZmxFLdoA", {
    "name": "Item name", "order": 300
  },
  // move checklist item to another checklist
  "y3BDYVqdjV2dgOCk8.items.ggn7vWR41zloeApCW", null,
  "w8lpvGxgi5yP1T6CE.items.ggn7vWR41zloeApCW", {
    "name": "existing item", "order": 400, "checked": true
  },
  // update checklist item name
  "w8lpvGxgi5yP1T6CE.items.S6bZMyUui7lOBgFpH.name.$partial", [
    '$append', '. I am appended'
  ]
]}}                

response

204 - No content - update was successful

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

404 - Not found

PUT /tickets?ids=<id_list>

Update details for multiple tickets. Fields are sent as a JSON body. Only specify the fields to be changed on all tickets.

parameterdescription
idsA comma separated list of ids to change
Any field can be changed but some changes may not be acceptable to all tickets selected. If a validation error occurs on any ticket the whole transaction will fail. Only the first failure will be reported.

response

204 - No content - update was successful

400 - application/json {<first-id-to-fail>: {<field>: [<list-of-errors>], ...}} A map of field errors found

404 - Not found

POST /tickets/<_id>

Create a ticket with the specified fields. Fields are sent as a JSON body.

parameterdescription
_idA unique id for the ticket
fielddescription
name (required)The name of the ticket
rtformatThe description is 'text' or in 'html' markup format
descriptionThe description for the ticket
bin_idThe id for the bin the ticket is in. (conflicts with enclosed_id)
enclosed_idThe id for the ticket to enclose this ticket in (conflicts with bin_id)
ticketType_id (required)The id for the ticket-type of this ticket
orderThe position of the ticket within the bin - defaults to end of list
assigned_idsA list of user_ids to assign to this ticket
watch_idsA list of user_ids that are watching this ticket
<standard-field>See get ticket
checklists A map of checklists in the form:
{<cl_id>: {
 name: "name of checklist", order: position when listed,
 items: {<it_id>: {
  name: "name of item",
  order: position when listed,
  checked: true or false },
 ...}},
...}

where cl_id and it_id are unique ids.
customFields A map of customFields in the form: {<cf_id>: value, ...}
where cf_id is the id of a custom field and value is conforming to the custom form's type.

The cf_id should correspond to a custom-field set in the ticket-type but this is not enforced.

response

204 - No content - Creation was successful

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

400 - application/json {_id: [["is_invalid"], ["already_exists"], ["not_unique"]]} already_exists indicates a ticket already has this id

PUT /tickets/<verb>?ids=<id_list>&parent_id=<parent_id>

Add or remove the parent of a list of tickets.

parameterdescription
id_listthe ids of the tickets to modify
verbeither addParent or removeParent

response

204 - No content - Update was successful

400 - application/json {<status>: [["is_invalid"]]}

PUT /tickets/<_id>/<verb>

Archive or restore a ticket

PUT /tickets/<verb>?ids=<id_list>

Archive or restore a list of tickets. Note: deleted tickets can also be restored here.

parameterdescription
_idthe id of the ticket to update; or
id_listthe ids of the tickets to update
verbeither archive or restore

response

204 - No content - Update was successful

400 - application/json {<status>: [["is_invalid"]]}

DELETE /tickets/<_id>

Delete a ticket

DELETE /tickets?ids=<id_list>

Delete a list of tickets

response

204 - No content - Delete was successful

404 - Not found

/tickets/<ticket_id>/attachments

Upload, download, delete and list ticket attachments.

Methods

GET /tickets/<ticket_id>/attachments/<id>

Download an attachment

parameterdescription
ticket_idThe ticket id
idThe attachment id

response

200 - media-type

404 - Not found

400 - application/json {ticket_id: [["is_required"], ["is_invalid"]]} - or access not allowed

example

get /tickets/DwPkagsKnisNbnmhb/attachments/48737ba16c26eba6b0927cb91d22edb7.txt

200 - text/plain

The contents of a text file
          

GET /tickets/<ticket_id>/attachments

Return list of attachments for the specified ticket_id. The attachments are in order of when attached.

response

200 - application/json

400 - application/json {ticket_id: [["is_required"], ["is_invalid"]]} - or access not allowed

example

get /tickets/DwPkagsKnisNbnmhb/attachments

[{
  "id":"48737ba16c26eba6b0927cb91d22edb7.txt",
  "name":"The-name-of-file.txt"
}, {
  "id":"68a820d82274702259f79ab210514371.png",
  "name":"a-picture.png"
}]
          

POST /tickets/<ticket_id>/attachments?name=<filename>

Create a ticket attachment. The content is the raw body. The Content-Type and Content-Length http headers should be set to match the content. Identical uploads are ignored. The response, if successful, will contain the id of the upload which is contructed using the md5 sum of the content followed by the filename suffix.

parameterdescription
ticket_idThe id of ticket to attach to
nameThe filename of the attachment not including the directory path

response

200 - application/json

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

example

curl -X POST --data-binary @path/to/my-attachment.dat -H "Content-Type: application/octet-stream" \
https://sd1.vimaly.com/rest/2/demo/tickets/DwPkagsKnisNbnmhb/attachments?name=my-attachment.dat

{
  "id":"ba6b0927cb91d22edb748737ba16c26e.dat",
  "name":"my-attchment.dat"
}
          

DELETE /tickets/<ticket_id>/attachments/<id>

Delete a ticket attachment

response

204 - No content - Delete was successful

404 - Not found

/ticket-comments

Create, update and inquire about ticket comments.

Methods

GET /ticket-comments/<_id>?rtformat=text|html

Return details for specified ticket comment

parameterdescription
_idThe ticket comment id
rtformatIf set to "html" returns the comment content as html markup

response

200 - application/json

404 - Not found

example

get /ticket-comments/DwPkagsKnisNbnmhb?rtformat=html

{
  "_id":"DwPkagsKnisNbnmhb",
  "comment":"This is a bold comment",
  "ticket_id":"XxcXo2NQq3sHcuMfW",
  "user_id":"9P3ubgAqygpr2kmKW",
  "createdAt":"2017-07-23T04:50:05.123Z",
  "updatedAt":"2017-07-23T04:50:05.123Z"
}
          

GET /ticket-comments?ticket_id=<ticket_id>

Return list of comments for the specified ticket_id. The comments are in descending order of creation.

response

200 - application/json

400 - application/json {ticket_id: [["is_required"], ["is_invalid"]]} - or access not allowed

example

get /ticket-comments?ticket_id=9P3ubgAqygpr2kmKW?rtformat=html

[{
  "_id":"DwPkagsKnisNbnmhb",
  "comment":"This is a bold comment",
  "ticket_id":"XxcXo2NQq3sHcuMfW",
  "user_id":"9P3ubgAqygpr2kmKW",
  "createdAt":"2017-07-23T04:50:05.123Z",
  "updatedAt":"2017-07-23T04:50:05.123Z"
}, {
  "_id":"NQq3sHcuMfWXxcXo2",
  "comment":"another comment",
  "ticket_id":"nisNbnmhbDwPkagsK",
  "user_id":"9P3ubgAqygpr2kmKW",
  "createdAt":"2017-07-25T14:20:15.123Z",
  "updatedAt":"2017-07-26T06:30:47.132Z"
}]
          

PUT /ticket-comments/<_id>

Update ticket comment content. Fields are sent as a JSON body. Only the comment field may be changed.

parameterdescription
_idThe ticket comment id
fielddescriptionexample
rtformatThe comment is 'text' or in 'html' markup format
commentThe comment content

response

204 - No content - update was successful

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

404 - Not found

POST /ticket-comments/<_id>

Create a ticket comment with the specified fields. Fields are sent as a JSON body.

parameterdescription
_idA unique id for the comment
fielddescriptionexample
rtformatThe comment is 'text' or in 'html' markup format
commentThe comment content
ticket_idThe id for the ticket the comment is in.

response

204 - No content - Creation was successful

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

400 - application/json {_id: [["is_invalid"], ["already_exists"], ["not_unique"]]} already_exists indicates a ticket already has this id

DELETE /ticket-comments/<_id>

Delete a ticket comment

response

204 - No content - Delete was successful

404 - Not found

/webhooks

Webhooks allow notifications for events to be posted to an external URL. Currently "ticket-update" is the only supported eventType.

A ticket creation, modification or delete which matches the event-config will generate a POST notification to the specified url. The content of the notification is a list of records. Each record includes the following fields:

example ticket notification

POST /url/path

response => {
  updateType: 'changed',
  updatedAt: '2018-05-15T01:32:53.808Z',
  updateId: '7',
  'content-type': 'ticket',
  content:
   { _id: 'c2H57QBmbRHkyA6D9',
     name: 'Hard disks rattling incessantly',
     bin_id: '8RTCXCjyDiyQNy6yE',
     updatedAt: '2018-05-15T01:32:53.808Z' },
  previousValues:
   { bin_id: 'atQT2NQ4FiOpL5pJ8',
     updatedAt: '2018-05-13T06:34:18.217Z' } }
        

example ticket comment notification

POST /url/path

response => { updateType: 'added',
  updatedAt: '2018-05-15T01:37:54.306Z',
  updateId: '11',
  'content-type': 'ticket-comment',
  ticket:
   { _id: 'c2H57QBmbRHkyA6D9',
     name: 'Hard disks increasing incessantly' },
  content:
   { _id: 'fWFVU7mctre4sFzjZ',
     comment: 'Order new hard disk,
     user_id: 'adminuidgj',
     createdAt: '2018-05-15T01:37:54.306Z',
     ticket_id: 'c2H57QBmbRHkyA6D9',
     updatedAt: '2018-05-15T01:37:54.306Z' } }
        

Reliable Delivery

Vimaly will attempt to deliver notifications to your application in a reliable way. However, be aware that notifications can be delayed indefinitely, and timeliness is not guaranteed. Since your application might not always be available, the following rules are followed when delivering notifications:

  1. If a notification delivery attempt fails, additional attempts will be made. The interval between additional delivery attempts is determined by an exponential backoff algorithm that starts with a retry 30-40 seconds after the initial failure. Subsequent deliveries are attempted at increasing intervals, up to a maximum interval of around 90 minutes. After the maximum retry interval of 90 minutes is reached, subsequent retries continue roughly every 90 minutes for 7 days. If the notification cannot be delivered in that time, the webhook will be purged.
  2. If your application cannot be reached after 20 seconds or if your application responds with an HTTP response code from 500-599, the notification delivery attempt is treated as a failure and is retried.
  3. If your application responds with one of the following HTTP response codes, the notification is treated as successfully delivered:
    102 Processing
    200 OK
    201 Created
    202 Accepted
    204 No Content
                
    Any other HTTP response codes returned by your application are treated as permanent failures and are not retried.

Note: Because of the retry mechanism above, it is possible that notifications are delivered more than once. Ensure that your application is idempotent with respect to processing a unique update record.

Methods

GET /webhooks/<_id>

Return details for a specified webhook

parameterdescription
_idThe webhook id

response

200 - application/json

example

get /webhooks/B3bYp9Jrwi8NwSQqE

{
  "_id":"B3bYp9Jrwi8NwSQqE",
  "name":"my webhook",
  "createdAt":"2017-07-24T04:50:05.123Z",
  "updatedAt":"2017-07-24T04:50:05.123Z",
  "last-successful-notification":"2017-08-24T04:50:05.123Z",
  "oldest-pending-notification":"2017-08-24T05:50:05.123Z",
  "config":{
    "url":"https://my.example.com/vimaly-webhook",
    "include-fields":["github-ref"]
  },
  "eventType":"ticket-update",
  "eventConfig":{
    "ticketTypes": ["XxcXo2NQq3sHcuMfW", "uD2s7qPlj8hhMhy"]
    "bins": [
      "aajmQbUOXGg5RtA67",
      "icjI6J9bx3XiCwzAV",
      "ACwza47jMQOF8fnkn"
    ],
  }
}
          

404 - Not found

GET /webhooks

Return list of webhooks for the organization

response

200 - application/json

example

get /webhooks

[{
  "_id":"B3bYp9Jrwi8NwSQqE",
  "name":"my webhook",
  "createdAt":"2017-07-24T04:50:05.123Z",
  "updatedAt":"2017-07-24T04:50:05.123Z",
  "config":{
    "url":"https://my.example.com/vimaly-webhook"
  },
  "eventType":"ticket-update",
  "eventConfig":{
    "bins": [
      "UOXGg5RtA67aajmQb",
      "6J9bx3XiCwzAVicjI",
      "a47jMQOF8fnknACwz"
    ]
  }
},{
  "_id":"wi8NwSQqEB3bYp9Jr",
  "name":"another webhook",
  "createdAt":"2017-05-04T04:50:05.123Z",
  "updatedAt":"2017-05-21T14:05:35.213Z",
  "config":{
    "url":"https://another.example.com/vimaly-hook"
  },
  "eventType":"ticket-update"
}]
          

GET /webhooks/<_id>/test

Test the specified webhook with a test message. The test message is sent as a POST. The message will only be sent once regardless of success.

parameterdescription
_idThe webhook id

response

204 - application/json

400 - application/json {"config.url": [["test message unsuccessful", <reason>, <response-body>]]}
invalid response or timeout from test message

example

get /webhooks/B3bYp9Jrwi8NwSQqE/test

// a message like the following will be sent to the webhooks configured url as a POST

[{
  "updateType": "test",
  "updaredAt": "2018-03-18T23:26:33.738Z",
  "updateId": "R4iMdEi0P29XVihhu"
}]
          

404 - Not found

POST /webhooks/<_id>

Create a webhook with the specified fields. Fields are sent as a JSON body. Before the webhook is created a test message is sent; if the message does not respond with a success code within 20 seconds, the webhook is not created and an explanation message is returned.

parameterdescription
_idA unique id for the webhook
fielddescription
name (optional)The name of the webhook
configThe configuration of the webhook messages (see below)
eventTypeThe type of event to observe. Currently only "ticket-update" is supported
eventConfigThe criteria for matching events (see below). If two filter fields are supplied both have to match for hook to be applied.

Note: an update matches if either the before or after fields match.

config

fielddescription
url Post event data to this url.
secret (optional) If provided, the secret will be used as the key to generate the sha-256 HMAC hex digest value of the post body in the X-Vimaly-Signature header.
max-results The maximum number of notifications to bundle together. If a failure occurs on a link then the retry will only send one notification until a successful retry. Defaults to 200.
include-fields (optional) An array of field names to always include in the notification records. Note that any field that changes is always included. The _id field is always included.

event-config for ticket-update

fielddescription
ticketTypes [id-list] any of the ids match a ticket's ticketType.
bins [id-list] any of the ids match a ticket's current bin.

response

204 - No content - Creation was successful

400 - application/json {"config.url": [["test message unsuccessful", <reason>, <response-body>]]}
invalid response or timeout from test message

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

400 - application/json {_id: [["is_invalid"], ["already_exists"], ["not_unique"]]} already_exists indicates a webhook already has this id

PUT /webhooks/<_id>

Update a webhook with the specified fields. Fields are the same as POST (create)

response

204 - No content - Update was successful

400 - application/json {<field>: [<list-of-errors>], ...} A map of field errors found

DELETE /webhooks/<_id>

Delete a webhook

response

204 - No content - Delete was successful

404 - Not found

User group access levels

Boards and Bins contain a list of user-group access levels which are used to restrict access to tickets.

An entry in the list is of the form: {"id":<user-group-id>,"al":<access-level>} where <user-group-id> corresponds to a user-group and <access-level> is one of the following:

100 - READ, 200 - USE, 300 - DESIGN and 400 - OWNER.
A user is given access corresponding to the highest <access-level> for all <user-group-ids> they belong to.

The <user-group-id> "all" is a special group which all users belong to.