NAV Navbar
json
  • Introduction
  • Configuration
  • Operation
  • Usage
  • DDP Compatibility
  • Connecting and Authenticating
  • Subscriptions
  • Collections
  • Field Types
  • Methods
  • Introduction

    The Hansoft web service provides access to a subset of data from the Hansoft server and operations via a WebSocket connection using the DDP protocol.

    The following information can help you understand how the web service works and provides detailed information and examples.

    For additional help, contact support@hansoft.com.

    Configuration

    Config file structure

    {
        "ListenAddress": <Hostname or IP address to listen for incoming connections on>,
        "ListenPort": <Port number to listen for incoming connections on>,
        "HansoftHost": <Hostname or IP address of the Hansoft server to connect to>,
        "HansoftPort": <Port number of the Hansoft server to connect to>,
        "HansoftDatabase": <The name of the database to expose via the web service>,
        "HansoftUser": <Username for a valid SDK user on the Hansoft server to use>,
        "HansoftPassword": <Password for the specified SDK user>,
        "HansoftRetryTimer": <Retry timeout in seconds if the SDK connection fails>,
        "HansoftAuthenticationTimer": <Timeout in seconds for authentication requests>
    }
    

    The web service is configured using a JSON configuration file named HansoftWebServiceConfig.json. This file is read from the WebService startup directory.

    In the config file, you can configure how the web service listens for incoming web sockets connections and the Hansoft server and database it should connect to. The web service requires Hansoft Server 9.3 or later.

    Example config file

    {
        "ListenAddress": "localhost",
        "ListenPort": 8086,
        "HansoftHost": "localhost",
        "HansoftPort": 50256,
        "HansoftDatabase": "Test1",
        "HansoftUser": "WebService",
        "HansoftPassword": "hpmsdk",
        "HansoftRetryTimer": 10.0,
        "HansoftAuthenticationTimer": 20.0
    }
    

    Operation

    The web service connects and authorizes to the Hansoft server specified in the config file.

    A log file named HansoftWebService.log is located in the Log directory in the WebService startup directory. It a good source of information for troubleshooting if issues occur with the web service. When the web service restarts, the existing log file is renamed with the current timestamp and a new log file is created.

    After the web service connects and authorizes with the Hansoft server, it starts listening for incoming WebSocket connections on the specified address and port.

    Note: The web service does not implement HTTPS for incoming WebSocket connections. The web service should be behind a web server that provides HTTPS connections for general access and forwards data to the web service. In a production environment, the nginx web server performs well. In development environments, a simple node.js application can be used.

    Usage

    The web service exposes access to a limited set of data and tasks via the DDP protocol over a WebSocket connection.

    You should be familiar with WebSockets and the DDP protocol if you are developing applications that use the web service.

    When accessing the web service from a JavaScript-based application (either in a browser or via node.js), we recommend using a DDP client library such as ddp.js (https://github.com/mondora/ddp.js/).

    If you are familiar with REST-based web APIs, make sure you understand the key differences and advantages offered by the DDP & WebSockets API used by the web service:

    DDP Compatibility

    The web service follows the DDP protocol described in https://github.com/meteor/meteor/blob/devel/packages/ddp/DDP.md with one exception:

    DDP removed messages are used to remove documents from a collection. If a removed message is received without an id field, the entire collection specified in the collection field should be removed from the client.

    The web service expects to receive and sends one DDP message per text payload WebSocket packet. This is not specified in the DDP specification, but is a common requirement of third-party DDP libraries.

    Connecting and Authenticating

    {
        "msg": "method",
        "method": "authenticate",
        "params": [ <UsernameString>, <PasswordString> ],
        "id": <ClientSpecificMethodID>
    }
    

    Connections to the web service move through a number of states during normal operation:

    When in the Connected state, the client should start the authorization process by issuing an authenticate method call:

    Receiving this method call by the web service transitions the connection to the Authorising state. While in this state, no additonal operations are allowed by the client.

    The web service then attempts to authenticate the user against the Hansoft server. When authentication completes (either success or failure), the web service sends a result message to the client.

    If authentication is successful, the web service responds with:

    {
        "msg": "result",
        "id": <ClientSpecificMethodID>,
        "result": {
            "success": true,
            "authResult": 0
        }
    }
    

    The connection transitions to the Authorised state.

    If authentication fails, the web service responds with:

    {
        "msg": "result",
        "id": <ClientSpecificMethodID>,
        "result": {
            "success": false,
            "authResult" <1 | 2 | 3>
        },
        "error": {
            "error": <Brief Description String>
            "reason": // OPTIONAL
            "message": // OPTIONAL
        }
    }
    

    The connection transitions back to the Connected state. The client can attempt to authorize again.

    When authentication fails, the authResult field in the result data is one of the following integers:

    1   Invalid Credentials (Username or password was invalid)
    2   Time Out (Authentication took too long)
    3   Error (An unknown error occured and the web service log should be reviewed)
    

    When a connection is made, it is in the Accepted state. The client then completes a DDP handshake with the web service. If the handshake is successful, the connection transitions to the Connected state. If the handshake is unsuccessful, the connection transitions to the Failed state and the client should disconnect.

    When in the Authorised state, the client can issue any permitted commands to the web service.

    Subscriptions

    {
        "msg": "sub",
        "id": <ClientChosenSubIDString>,
        "name": <SubscriptionNameString>,
        "params": <ArrayOfParams> // OPTIONAL
    }
    
    {
        "msg": "nosub",
        "id": <ClientChosenSubIDString>,
        "error": <ErrorObject> // OPTIONAL
    }
    
    {
        "msg": "ready",
        "subs": [ <ClientChosenSubIDString> ]
    }
    

    Subscriptions are made using a standard DDP subscribe message.

    If the subscription attempt fails, a DDP nosub message is returned.

    If the subscription attempt is successful, the client receives updates (added, changed, removed DDP messages) for the current state of data covered by the subscription followed by a DDP ready message.

    The client will then receive updates to data covered by the subscription as the web service becomes aware of them.

    Subscription: MyWork

    The MyWork subscription covers one collection, which is also called MyWork. This collection contains one document for each task currently assigned to the user. See the Collection: MyWork section for more information.

    This subscription does not accept any parameters.

    Subscription: ProjectMeta

    The ProjectMeta subscription covers one collection for each project the user is in (including planning, backlog and QA projects). These collections are named ProjectMeta_<ProjectID> and contain information about the project in the document with the $Project key and additional documents for each field tasks in the project can potentially have. See the Collection: ProjectMeta_<ProjectID> section for more information.

    This subscription does not accept any parameters.

    Subscription: ProjectResources

    The ProjectResources subscription covers one collection for each planning project the user is in (no collections for backlog or QA projects). These collections are named ProjectResources_<ProjectID> and contain one document for each resource or resource group in the project. See the Collection: ProjectResources_<ProjectID> section for more information.

    This subscription does not accept any parameters.

    Subscription: TaskComments

    {
        "msg": "sub",
        "id": <ClientChosenSubIDString>,
        "name": "TaskComments",
        "params": [ <TaskIDString> ]
    }
    

    The TaskComments subscription covers one collection named TaskComments_<TaskID>, which contains all comments for the specified task. The task ID to use to subscribe to comments is specified in the subscription parameters as the only argument. More than one TaskComments subscription can be created at a time.

    See the Collection: TaskComments_ section for more information.

    Collections

    Collection: MyWork

    A MyWork collection contains one document for each task currently assigned to the user.

    The key of each document is the string representation of the task database ID.

    Each field in a task document represents a task field in Hansoft. The key for each field is referred to as a task field name. These names are strings used to identify a task field and make it easier for developers to locate the task fields they are interested in. They are not designed to be displayed to end users and are never localized. For custom columns, the field name used has the following format: "CC_<ColumnHash>". The value of each field in a task document represents the value of the task field in Hansoft.

    To interpret the value of a task field and find a field name to display to the user, see the ProjectMeta_<ProjectID> collection that corresponds to the project the task is in.

    Each task document has two fields that are always present: * $ID stores the task's database ID as a string (same value used as the key for a task document). * ProjectID stores a string of the ID of the project the task is in.

    For example, assume you subscribed to MyWork and ProjectMeta:

    Collection: ProjectMeta_<ProjectID>

    {
        "ProjectMeta_<ProjectID>": {
            "$Project": {
                "Name": <ProjectNameString>,
                "SortName": <ProjectSortNameString>,
                "Type": <"Planning" or "Backlog" or "QA">,
                "Backlog": <BacklogProjectIDString>, // Only for non-backlog projects
                "QA": <QAProjectIDString>, // Only for non-QA projects
                "Planning": <PlanningProjectIDString> // Only for non-planning projects
            }
        }
    }
    
    {
        "ProjectMeta_<ProjectID>": {
            "$Project": <ProjectInfo>,
            "WorkRemaining": {
                "DisplayName": "Work Remaining",
                "Type": "Hours"
            }
        }
    }
    

    A ProjectMeta collection contains information about the project in the document with the special key $Project.

    The other documents in a ProjectMeta collection represent fields for tasks in the project. These documents are referred to as field meta documents. The document IDs are the task field names. The contents of the document specify the field display name (in the DisplayName field to display to the end user), the field type (in the Type field for interpretation), and optional additional information depending on the type.

    The Type field is a JSON string. Valid values and any additional fields are described in the Field Types section.

    Collection: ProjectResources_<ProjectID>

    {
        "ProjectResources_<ProjectID>": {
            <ResourceIDString>: {
                "Name": <ResourceNameString>,
                "SortName": <ResourceSortNameString>, // OPTIONAL
                "Type": <ResourceTypeInteger>
            }
        }
    }
    

    The Type field has one of the following numeric values:

    1   Resource is a normal user
    2   Resource is a SDK user
    3   Resource is a ghost user 
    4   Resource is a QA user
    

    For example:

    {
        "ProjectResources_1023": {
            "84": {
                "Name": "Dougal Langley",
                "Type": 1
            },
            "85": {
                "Name": "Percy Woodrow",
                "Type": 1
            },
            "85": {
                "Name": "SDKUser",
                "Type": 2
            }
        }
    }
    

    A ProjectResources collection contains one document for each resource or resource group in the specified project. A ProjectResources collection only exists for planning project IDs, not for backlog or QA project IDs. The ProjectMeta_<ProjectID> collection for a project can be used to find the planning project ID for a backlog or QA project.

    Each document has a string representation of a resource ID as its key. The contents use the format displayed on the right.

    Collection: TaskComments_<TaskID>

    {
        "PostedBy": <NameOfResourceString>,
        "PostedByID": <ResourceIDString>,
        "PostedAt": [ <Year>, <Month>, <DayOfMonth>, <Hour>, <Minute>, <Second> ],
        "ParentID: <ParentPostIDString>,
        "Flags": <FlagsNumber>,
        "Text": <CommentTextInHansoftFormat>
    }
    

    The Flags field is a bitfield that may contain the following flags:

    Bit     Value       Description
    0       1           The comment is posted and should be visible.
    1       2           The comment is currently being edited by a resource.
    
    "TaskComments_<TaskID>": {
        "12": {
            "PostedBy": "Geralt Barnacle",
            "PostedByID": "120",
            "PostedAt": [ 2018, 2, 19, 14, 53, 2 ],
            "ParentID": "-1",
            "Text": "I tried this today with no luck. I will try again tomorrow."
        }
    }
    

    A TaskComments collection contains all comments for one task. Each comment is stored as a document with the comment's post ID as a string as the key.

    Each comment document uses the format displayed on the right.

    A parent ID of -1 indicates that the comment is not a reply.

    See the Hansoft help for information about the comment text format.

    Field Types

    The following information describes the JSON value types for each task field type. You can expect these value types in a MyWork task document for a field of the specified type. These value types are also, unless otherwise specified, what you should provide the method SetTaskField with when setting a field of the specified type.

    Field Type: String

    The value is a JSON string and expected to be displayed on one line.

    No other meta document fields are present.

    Field Type: MultiLine

    The value is a JSON string and is expected to be displayed as multiple lines of text.

    No other field meta document fields are present.

    The value is a JSON string that is a URL and is expected to be displayed as a clickable link.

    No other meta document fields are present.

    Field Type: Integer

    "IntegerField": {
        "DisplayName": "Integer Field",
        "Type": "Integer",
        "Unit": "days"
    }
    

    The value is a JSON number and always a 32-bit signed integer.

    An optional field named Unit may be present, which contains a JSON string of the units the field value is in. The Unit field is only for display purposes. Hansoft and the web service do not use this value.

    Field Type: Float

    "FloatField": {
        "DisplayName": "Float Field",
        "Type": "Float",
        "Unit": "kg"
    }
    

    The value is a JSON number and always a 32-bit floating point value.

    An optional field named Unit may be present, which contains a JSON string of the units the field value is in. The Unit field is only for display purposes. Hansoft and the web service do not use this value.

    Field Type: DateTime

    The value is a JSON array that contains three JSON numbers, which represent a date in the format:

    [ <Year>, <Month>, <DayOfMonth> ].

    No other meta document fields are present.

    Field Type: DateTimeTime

    The value is a JSON array that contains six JSON numbers, which represent a date and time in the format:

    [ <Year>, <Month>, <DayOfMonth>, <HourOfDay>, <MinuteOfHour>, <SecondOfMinute> ]

    No other meta document fields are present.

    Field Type: Enum

    
    {
        "MyWork": {
            "86": {
                "$ID": "86",
                "ProjectID": "1021",
                "Status": 1,
                <Other Task Fields>
            }
        },
        "ProjectMeta_1021": {
            "Status": {
                "DisplayName": "Completion Status",
                "Type": "Enum",
                "Enum": [
                        [ 0, "Not Done" ]
                    ,   [ 1, "In Progress" ]
                    ,   [ 2, "Done" ]
                ]
            },
            <Other Field Meta Data for Project 1021>
        }
    }
    

    The value is a JSON number that represents a choice ID from a predetermined list of choices. The field meta document has a field named Enum, which is a JSON array with a choice ID (JSON number) and a choice name (JSON string) in a two element array.

    Field Type: MultiEnum

    {
        "MyWork": {
            "86": {
                "$ID": "86",
                "ProjectID": "1021",
                "MultipleChoice": {
                    "Value": [ 0, 2 ],
                },
                <Other Task Fields>
            }
        },
        "ProjectMeta_1021": {
            "MultipleChoice": {
                "DisplayName": "Multiple Choice",
                "Type": "MultiEnum",
                "Enum": [
                        [ 0, "Apples" ]
                    ,   [ 1, "Oranges" ]
                    ,   [ 2, "Pears" ]
                ]
            },
            <Other Field Meta Data for Project 1021>
        }
    }
    

    The value is a JSON array of JSON numbers. Each number represents a choice ID from a predetermined list of choices. The field meta document has a field named Enum, which is a JSON array with a choice ID (JSON number) and a choice name (JSON string) in a two element array.

    Field Type: InlineEnum

    {
        "MyWork": {
            "86": {
                "$ID": "86",
                "ProjectID": "1021",
                "WorkflowStatus": {
                    "Value": 0,
                    "Enum": [
                        [ 0, "Step 1" ],
                        [ 1, "Step 2A" ],
                        [ 2, "Step 2B" ]                    
                    ]
                },
                <Other Task Fields>
            }
        },
        "ProjectMeta_1021": {
            "WorkflowStatus": {
                "DisplayName": "Workflow Status",
                "Type": "InlineEnum"
            },
            <Other Field Meta Data for Project 1021>
        }
    }
    

    The value is a JSON object that contains a Value field, which is a JSON number that represents a choice ID, and an Enum field that contains a list of choice IDs and names in the same format used for the Enum field in the fields meta document for Enum fields. This field type is used for situations where the potential choices for a drop down field depend on the current value of the field. This is used for the Workflow Status field in Hansoft.

    When using the SetTaskField method to change the value of an InlineEnum field, you must use a different format. Use the integer choice ID (not an object with a Value and Enum field).

    Field Type: Hours

    The value is a JSON number that represents a number of hours. The value can be fractional.

    No other meta document fields are present.

    Field Type: TimeZones

    "TimeZoneField": [
        [ 
            // Period 1 Start Time:
            [ <Year>, <Month>, <DayOfMonth>, <HourOfDay>, <MinuteOfHour>, <SecondOfMinute> ],
            // Period 1 End Time:
            [ <Year>, <Month>, <DayOfMonth>, <HourOfDay>, <MinuteOfHour>, <SecondOfMinute> ]
        ],
        [ 
            // Period 2 Start Time:
            [ <Year>, <Month>, <DayOfMonth>, <HourOfDay>, <MinuteOfHour>, <SecondOfMinute> ],
            // Period 2 End Time:
            [ <Year>, <Month>, <DayOfMonth>, <HourOfDay>, <MinuteOfHour>, <SecondOfMinute> ]
        ],
    ]
    
    {
        "MyWork": {
            "86": {
                "$ID": "86",
                "ProjectID": "1021",
                "TimeZones": [
                    [ [ 2018, 2, 15, 12, 00, 00 ], [ 2018, 2, 16, 12, 00, 00 ] ]
                ],
                <Other Task Fields>
            }
        },
        "ProjectMeta_1021": {
            "TimeZones": {
                "DisplayName": "Time",
                "Type": "TimeZones"
            },
            <Other Field Meta Data for Project 1021>
        }
    }
    

    Note: This field type is used to represent blocks (zones) of time on a task. It does not refer to time zones, such as GMT or UTC.

    The value is a JSON array of time periods. It is a two-element array with start and end times represented in the same format as DateTimeTime fields.

    Field Type: Resources

    The value is a JSON array of resource entries. Each entry uses the following format:

    [ <ResourceEntryTypeInteger>, <ResourceIDInteger>

    <ResourceEntryType> specifies the resource type.

    1   ResourceID specifies a normal resource ID
    2   ResourceID specified a resource group ID
    3   The resource entry represents all project members. ResourceID is ignored.
    
    {
        "MyWork": {
            "86": {
                "$ID": "86",
                "ProjectID": "1021",
                "CC_123844": [
                    [ 1, 23 ],
                    [ 1, 28 ],
                ],
                <Other Task Fields>
            }
        },
        "ProjectMeta_1021": {
            "CC_123844": {
                "DisplayName": "Custom Resource List",
                "Type": "Resources"
            },
            <Other Field Meta Data for Project 1021>
        }
    }
    

    Methods

    Methods are the only way for clients to request changes to the Hansoft server.

    Note: The optional randomSeed field of DDP method calls is never used or required by the web service.

    Method: SetTaskField

    {
        "msg": "method",
        "method": "SetTaskField",
        "params": [ "86", "Description", "Task Two" ],
        "id": "ClientSpecifiedMethodID"
    }
    
    {
        "msg": "result",
        "id": <ClientSpecifiedMethodIDString>,
        "result": {
            "success": true,
        }
    }
    

    If a SetTaskField method call fails, the web service responds with a DDP result message in the following format:

    {
        "msg": "result",
        "id": <ClientSpecificMethodIDString>,
        "result": {
            "success": false,
        },
        "error": {
            "error": <ErrorString>,
            "reason": <ReasonString>, // OPTIONAL
            "message": <MessageString> // OPTIONAL
        }
    }
    

    or:

    {
        "msg": "result",
        "id": <ClientSpecificMethodIDString>,
        "result": {
            "success": false,
            "RequiredFieldsMissing": <ArrayOfTaskFieldNameStrings>
        }   
    }
    

    Use the SetTaskField method to change the value of a task field. Any task that the user has permission to edit can be modified. This is limited to tasks currently assigned to the user. The SetTaskField method accepts three parameters:

    [ <TaskIDString>, <TaskFieldNameString>, <NewValue> ]

    An example of a DDP method call for SetTaskField is displayed on the right.

    The type of the new value specified depends on the field type being set, which can be queried from the corresponding ProjectMeta collection. See the Field Types section for the specific JSON value format for each field type.

    When a SetTaskField method call is made, the web service attempts to make the change. If successful, the client receives DDP messages describing the changes followed by a DDP result message.

    Setting a single task field may result in additional changes. This can occur when setting the WorkflowStatus column as transitioning to another workflow stage, which may result assigning the task to a different user.

    On the right, RequiredFieldsMissing contains a list of task field names that must have values set before the SetTaskField method is allowed. This is used for WorkflowStatus fields when a workflow requires setting specific fields.

    Method: TaskPostComment

    {
        "msg": "method",
        "method": "TaskPostComment ",
        "params": [ "86", -1, "My comment" ],
        "id": "ClientSpecifiedMethodID"
    }
    
    {
        "msg": "result",
        "id": <ClientSpecifiedMethodIDString>,
        "result": {
            "success": true,
        }
    }
    
    {
        "msg": "result",
        "id": <ClientSpecificMethodIDString>,
        "result": {
            "success": false,
        },
        "error": {
            "error": <ErrorString>,
            "reason": <ReasonString>, // OPTIONAL
            "message": <MessageString> // OPTIONAL
        }
    }
    

    The TaskPostComment method is used to post a new comment on a task. Any task the user has permission to access can have a comment posted on it. TaskPostComment accepts three parameters:

    [ <TaskIDString>, <ParentPostIDOrMinusOneString>, <CommentTextString> ]

    An example of a DDP method call for TaskPostComment is displayed on the right.

    If the method call succeeds, a DDP result message with the Success result field set to true is returned.

    If the method call fails, the response has the Success result field set to false and an DDP error field is present.

    Method: TaskEditComment

    {
        "msg": "method",
        "method": "TaskEditComment ",
        "params": [ "86", 12, "My updated comment" ],
        "id": "ClientSpecifiedMethodID"
    }
    
    {
        "msg": "result",
        "id": <ClientSpecifiedMethodIDString>,
        "result": {
            "success": true,
        }
    }
    
    {
        "msg": "result",
        "id": <ClientSpecificMethodIDString>,
        "result": {
            "success": false,
        },
        "error": {
            "error": <ErrorString>,
            "reason": <ReasonString>, // OPTIONAL
            "message": <MessageString> // OPTIONAL
        }
    }
    

    The TaskEditComment method is used to edit a comment a user previously made on a task. TaskEditComment accepts three parameters:

    [ <TaskIDString>, <PostIDString>, <CommentTextString> ]

    An example of a DDP method call for TaskEditComment is displayed on the right.

    If the method call succeeds, a DDP result message with the Success result field set to true is returned.

    If the method call fails, the response has the Success result field set to false and an DDP error field is present.