The Command API
The Command API defines how command responses control the HSYCO client.
Status
Returning a command response normally logs an [OK] status.
To prevent the command from being written to the log file, for example to avoid sensitive information being written in the log, either prefix a string response with ! or set "log": false in a JSON response.
For string responses, the leading ! is removed before the response is sent to the client, so ! suppresses logging with no response text, while !page:home suppresses logging and still sends page:home.
For JSON responses, "log": false only suppresses the server log; the rest of the response is still processed normally.
Specific response strings can be used to provide feedback to the user, or to navigate the interface.
For more advanced errors, JSON responses can be used. JSON can combine more than one action in a single response, and can also disable logging. In Javascript Events, JSON objects can be returned directly:
function userCommand(session, userid, name, param) : {
return { "error": "An error occurred", "log": false };
}
In Java Events, JSON objects have to be converted to a string:
static String userCommand(String name, String param) {
return "{\"error\": \"An error occurred\"}";
}
static String userCommand(String name, String param) {
JSONObject json = new JSONObject();
json.put("error", "An error occurred");
return json.toString();
}
Navigation
The following responses can be used to navigate the interface:
page:<page name> - navigate to the specified page
page:back - navigate back
page:forward - navigate forward
page:close - close the current popup
page:close-all - close all popups
These can also be specified in JSON format:
{ "page": "<page name>" }
{ "page": "back" }
{ "page": "forward" }
{ "page": "close" }
{ "page": "close-all" }
Pages can also be specified as an array, to perform multiple navigation actions:
{ "page": ["close-all", "popup2"] }
This will close all popups and open the page "popup2".
If a page has been opened by a command action, the userCommand function will be called again when that page is closed, with "/close" appended to the param.
To navigate to a specific URL, use the following response:
{ "url": "<url>" }
{ "url": "<url>", "target": "<target>" } - open the url in the specified browser tab, can be "_self", "_blank" or a custom name
To specify the url of another project, you can use a relative path:
{ "url": "../<project name>", "target": "<target>" }
Toast
To display a toast message, use the following response:
{ "toast": "<message>" }
Toast can also be displayed with a specific duration in milliseconds:
{ "toast": { "message": "<message>", "duration": <duration> } }
An optional type can also be specified:
{ "toast": { "message": "<message>", "type": "<info|success|warning|error>" } }
By default, displaying a toast with the same message will refresh the duration of the existing toast. To force the display of a new toast, use the following response:
{ "toast": { "message": "<message>", "duplicate": true } }
To close a toast with a specific message, use the following response:
{ "toast": { "message": "<message>", "close": true } }
To open multiple toasts, you can specify an array of toast objects:
{ "toast": [ { "message": "<message1>", "duration": <duration1> }, { "message": "<message2>", "duration": <duration2> } ] }
Popup message
To display a popup message, use the following response:
{ "popup": "<message>" }
Popup can also be displayed with a specific title:
{ "popup": { "title": "<title>", "message": "<message>" } }
An optional type can also be specified:
{ "popup": { "title": "<title>", "message": "<message>", "type": "<info|success|warning|error>" } }
Error management
A command can return an error state and optional error message and display mode.
Simple error
For a simple error, return the error string:
error
Or return a JSON response with error set to true:
{ "error": true }
Error with message
For an error with a message, use the JSON format:
{ "error": "<message>" }
The default display mode is a tooltip.
Error with code
For one of the standard localized errors, use the JSON format:
{ "error": { "code": 500 } }
The client resolves the code using the localized error<code> text.
The standard error codes are:
| Code | Message |
|---|---|
| 400 | Invalid request |
| 401 | Authentication required |
| 403 | Not allowed for this user |
| 404 | Resource not found |
| 408 | Request timed out |
| 409 | The data was changed by another user |
| 422 | Invalid data |
| 429 | Too many requests |
| 500 | Internal error |
| 501 | Operation not supported |
| 503 | Service temporarily unavailable |
Error with display mode and timeout
To display the error with a specific display mode and/or timeout, use the following format:
{ "error": { "message": "<message>", "display": "<tooltip|popup|toast>", "timeout": "<ms>" } }
The optional timeout is the time in milliseconds before the error message disappears.
Tooltip will display at the bottom of the object that triggered the command, e.g. a button or field object.
Toast will display at the top right of the screen. This can be changed in the Project's attributes.
Popup will display a modal in the center of the screen.
Rollback
If the command is generated from an object with a value (field, slider, etc.), the value can be rolled back to the previously valid one by adding the "rollback" key to the response:
{ "error": "<message>", "rollback": true }
The valid value is the parameter of the last command generated from the object that did not return an error.
Form and submit errors
For a validation error associated with a specific field, return a JSON response with the fields property. This applies to Form responses, table or list add/edit popups, and Buttons with action="submit".
{
"error": "Check the highlighted fields",
"fields": {
"email": {
"error": "Enter a valid email address"
}
}
}
The top-level error displays a general message and is optional when the field messages are sufficient. See Updating fields below for the supported command contexts, field properties, and error behavior.
Updating fields
Forms, submit Buttons, and Edit Popups on Table, List, and Tree objects send requests with a set of editable fields. The response can update those same fields before the interaction continues.
This can be used to:
- report validation errors on specific fields
- normalize, calculate, or replace submitted values
- enable, disable, show, or hide fields
- update selectable items and other runtime field attributes
To update fields, return a top-level fields property. Use the same field names sent in the request:
{
"fields": {
"<field name>": {
"value": "<value>"
}
}
}
Supported contexts
The command that produced the response must provide a field context. The following responses support fields:
- a Button with
action="submit"; the response fromuserSubmittargets the fields collected from the Button's container - Form command responses for
submit,add,edit,edit-change, inline Button commands, and footer Button commands - datasource insert or update responses handled by a Form
- table or list edit-popup responses;
pre-add,pre-edit, andpre-duplicatecan initialize fields before the popup opens, whileedit-changeand add/edit responses apply to the active editor
Use the same field key sent in the command's field values. Depending on the context, this is the configured field name, datasource name, object name, or object ID. Fields that are not found in the current context are ignored.
Field properties
Most of these properties mirror the editable field attributes used by Forms and edit popups.
type- the field type; redraws the Form or popupvisible- shows or hides the item. In Forms and edit popups, invisible cells retain their space in partly visible rows; fully invisible rows collapse. Invisible fields skip validation and are submitted only ifsavevalueis"true"value- the field valueenabled- whether the field is enabled; disabled fields skip validation and are submitted only ifsavevalueis"true"placeholder- the placeholder textreadonly- whether the field is read onlyitems- the items of a select-like field initemsmodelist- the items of a select-like field inlistmodeprefix- the field prefixsuffix- the field suffixclearbutton- whether the clear button is visiblerequired- whether the field is requiredfocustooltip- the tooltip shown when the field is focusederror- set or clear the field error state (true,false, or an error message string)errormessage- the error message to use whenerroristruemultienabled- in multi-edit mode, whether the field is enabled for editingmultirequired- iftrue, include the field in multi-edit with no option to deselect it;requiredstill controls whether its value may be empty.
Attributes that affect layout can rebuild the Form or popup.
Field errors
Use the error property to set or clear a server-side validation error:
{ "fields": { "<field name>": { "error": true } } }
{ "fields": { "<field name>": { "error": true, "errormessage": "<message>" } } }
{ "fields": { "<field name>": { "error": false } } }
{ "fields": { "<field name>": { "error": "<message>" } } }
These forms mean:
true: set the field in error statetruewitherrormessage: set the field in error state and use the supplied messagefalse: clear the field error state"<message>": set the field in error state and use the string as its error message
Field errors do not require a top-level error property. They prevent the successful completion of a Form submit, add, or edit action; in an edit popup, this keeps the popup open. The first field in error is focused. The field or Form attributes (Error Display, Field Error Display) determine whether the message appears as a tooltip or inline.
Returning fields to a popup opener
As a special case, a command running in a nested popup can close that popup and update the page or popup that opened it in the same response:
{
"page": "close",
"fields": {
"customer": {
"value": "ACME"
}
}
}
The client closes the current popup first, then applies fields to the surface containing the Button or command sender that opened it.
The fields are discarded when:
- the popup has no recorded opener, for example when it was opened directly rather than from a link or command response
- the popup cannot close, for example because the page is locked
- the response uses
"page": "close-all" closeis combined with other navigation actions in the same response
This is useful, for example, for tools opened from a Form or edit popup: a calculator can collect parameters in a nested popup, close it, and return the calculated result to one or more fields in the opener. Other examples include record pickers, address searches, unit converters and pricing tools.
Clipboard Copy
To copy text to the clipboard, use one of the following responses:
copy:<text>
{ "copy": "<text>" }
Browser clipboard security rules require a user gesture before writing to the clipboard. For this reason, copy:<text> and { "copy": "<text>" } open a Copy popup in the web client instead of silently copying. The user must press Copy to complete the operation.
To copy immediately from a user click, use a Button with action clipboard-copy and set Clipboard Text; because the copy runs from the button interaction, no popup is needed.
Download
A command response can initiate a file download:
{ "download": { "name": "<command name>", "parameter": "<parameter>" } }
When the client receives this response, it sends a separate download request using the specified name and parameter.
Handling a download request
A download request calls userCommand with its command name and parameter. Implement the callback in JavaScript or Java.
A download request can be initiated:
- directly by an object with a
downloadaction - by the
downloadcommand response described above
For direct object actions, the object's Action documentation describes the exact parameter. Form inline buttons and footer buttons send the same JSON parameter used by their command actions, with action set to inline-button or footer-button. Their configured Button Name is included as button when set.
The callback must return one of the following:
- the full path of an existing file or directory; directories are downloaded as ZIP archives
- a JSON object with
pathand, optionally,filenameanddelete; whendeleteistrue, HSYCO deletes the source file after reading it - a JSON object with Base64-encoded
dataand afilename
{ "path": "userdata/report.pdf", "filename": "report.pdf", "delete": true }
{ "data": "<Base64-encoded data>", "filename": "report.pdf" }
Paths must identify files or directories accessible under the HSYCO main directory.
App
When the interface is loaded inside the HSYCO App (iOS or Android), you can send a specific command to the app by returning a string that starts with “app:“ followed by the command:
app:speech - enable speech recognition
app:codescan - enable qr/bar code scanning
To open the native share interface in the HSYCO App return:
{ "share": "<text>" }
In a web client, it opens the Copy popup.