3.4. Other clients

For other clients, a "REST level 0", or RPC-like interface is available, using JSON encoded strings for passing parameters and receiving results from services. Each service responds to POST requests to the following URL http[s]://cyclos.url/[network/]web-rpc/<short-service-name>, where the short-service-name is the service with the first letter as lowercase. So, for example, https://my.cyclos.instance.com/network/web-rpc/accountService is a valid URL, being mapped to AccountService. Other URLs are also supported, as described in Section 3.4.1, “URL mapping”

For authentication, the username and password should be passed as a HTTP header using the standard basic authentication – a header like: "Authentication: Basic <Base64-encoded form of username:password>". Actually, username or other principal type (user identification method) will be chosen according to the configuration. If the configuration allows more than one principal type, it is possible to specify a value in the "Principal-Type" header, which must match the principal type internal name. Alternatively, it is possible to login the user via LoginService and pass the obtained session token in the "Session-Token" header. A third access option is to use an access client token. In this case, the header "Authorization: Bearer <access client token>" is used to specify the access client token. Alternatively, the header Access-Client-Token can be passed in with the token as value.

To specify a channel, pass the header "Channel: <channel internal name>". If no channel is passed, Web Services is assumed.

When the URL is specified up to the service, as stated above, the request body must be a JSON object with the ‘operation’ and ‘params’ properties, where operation is the method name, and params is either an array with parameters, or optionally the parameter if the method has a single parameter (without the array) or even omitted if the method have no parameters. For objects, the parameters are expected to be the same as the Java counterparts (see the JavaDocs for a reference on the available properties for each object).

As result, if the request was successful (http status code is 200), an object with a single property called result will be returned. The object has the same structure as the object returned by the service method, or is a string, boolean or number for simple types. Requests which resulted in error (status code distinct than 200) will have the following structure:

3.4.1. URL mapping

Besides using the URL pointing to the service, and have the POST body as a JSON, selecting the operation and the parameters, it is also possible to choose the operation in the URL itself, as a subpath in the URL. For example, https://my.cyclos.instance.com/network/web-rpc/userService/search already maps to the search operation. The POST body, then, is expected to be just the JSON for the parameters, with the same rules as explained above: if is a single parameter, the body can be the JSON value directly, and if no parameters, the POST body can be empty.

Additionally, the service methods that are readonly can be invoked by GET requests. In this case, the parameter can be passed using 2 forms:

  • When the parameters are simple (just identifiers or internal names), they can be passed in as URL parts. For example, https://my.cyclos.instance.com/network/web-rpc/accountService/load/836144284089
  • When there is a single parameter of type object, it can be passed using URL parameters. For example: https://my.cyclos.instance.com/network/web-rpc/userService/search?keywords=shop&groups=business

Finally, services are mapped to other 2 URLs besides <name>Service: one without the 'Service' suffix, and another one, pluralized. Also, if an operation doesn't match, it will be attempted by prepending 'get' with the first letter capitalized. This will allow shorter urls on calls, like:

  • GET https://my.cyclos.instance.com/network/web-rpc/users/search?keywords=shop&groups=business is equivalent to GET https://my.cyclos.instance.com/network/web-rpc/userService/search?keywords=shop&groups=business
  • GET https://my.cyclos.instance.com/network/web-rpc/user/data/4534657457 is equivalent to GET https://my.cyclos.instance.com/network/web-rpc/userService/getData/4534657457

3.4.2. Details on JSON handling

All output objects, when converted to JSON, will have a property called class, which represents the fully-qualified Java class name of the source object. Most clients can just ignore the result. However, when sending requests to classes that expect a polymorphic object, the server needs to know which subclass the passed object represents. In those cases, passing the class property, with the fully qualified Java class name is required. An example is the AdService. When saving an advertisement, it could either be a simple advertisement (AdvertisementDTO) or a webshop advertisement (AdWebShopDTO). In this case, a class property with the fully qualified class name is required. Note, however, that in most cases, the class information is not needed.

Whenever a subclass of EntityVO is needed, numbers or strings are also accepted (besides objects). Numbers always represent the vo identifier (id property). Strings can either be id when they are numeric, or can represent one of the following cases:

  • When the type is BasicUserVO or a subclass, an UserLocatorVO is created, and the string represents the principal. If the string is 'self' (sans quotes) it will resolve to the logged user;
  • When the type is AccountVO, the string represents the account number;
  • When the destination VO has an internal name, the string represents it;
  • Otherwise, the VO is assumed to be null.

If the value is supposed to be a number handled as user principal (for example, a mobile phone) or account number, it must be prefixed with a single quote. For example, to represent a phone number as string, the following is accepted: '5187653456. If not prefixed, it would be interpreted as user id instead. The single quote prefix is the same as Excel / LibreOffice use to represent a number as string.

Other points to note with JSON handling:

  • Whenever a collection is expected, a single value can be passed, resulting in a collection with a single element;
  • Java long values (mostly identifiers) are always returned as string, because of the identifier ciphering, the whole 64-bit space is used. In JavaScript, however, integer numbers cannot use 64 bit, resulting in different numbers when reading from JSON.
  • Whenever dates are used (represented by the DateTime class) they are returned / expected to be strings in the ISO 8601 format, without timezone. For example, "2015-01-31T17:29:00" represent 31 January 2015, at 5:29 pm. Also, for input, the text "now" is accepted (without quotes) to represent the current time.

3.4.1. Examples

Assuming that the authentication header is correctly passed, the following request can be performed to search for users: POST https://my.cyclos.instance.com/network/web-rpc/userService with the following body:

{
    "operation": "search",
    "params": {
        "keywords": "user",
        "groups": "consumers",
        "pageSize": 5
    }
}

The resulting JSON will be something like:

{
    "result": {
        "currentPage": "0",
        "pageSize": "40",
        "totalCount": "2",
        "pageItems": [
            {
                "class": "org.cyclos.model.users.users.UserDetailedVO",
                "id": "-2717327251475675143",
                "display": "Consumer 1",
                "shortDisplay": "c1"
            },
            {
                "class": "org.cyclos.model.users.users.UserDetailedVO",
                "id": "-2717467988964030471",
                "display": "Consumer 3",
                "shortDisplay": "c3"
            }
        ]
    }
}

Note the params "groups" property of the input query is a collection of BasicGroupVO. It is being passed the string "consumers", which is matched to the group internal name.

The above request is equivalent to a POST to https://my.cyclos.instance.com/network/web-rpc/users/search (using the plural name) with the following body:

{
    "keywords": "user",
    "groups": "consumers",
    "pageSize": 5
}

Note only the parameters part is passed. If the service method would require multiple parameters, the body should be a JSON array. If a single string, the string should be quoted, just like in JSON.

Also, the above request is equivalent to a GET to https://my.cyclos.instance.com/network/web-rpc/user/search?keywords=user&groups=consumers&pageSize=5 (singular name). Only methods which take a single parameter object can use query parameters.