The SDK API enables SDK toolkits - e.g. the ZeyOS SDK CLI - to synchronize app data with ZeyOS.
First, you should login to your ZeyOS instance using the auth endpoint
.
Let's say, our ZeyOS instance is called "sdkdemo", then the full URL path would be: https://cloud.zeyos.com/sdkdemo/auth/v1/login
.
Example with CURL:
curl --data 'name=admin&password=demo&identifier=ZeySDK' https://cloud.zeyos.com/sdkdemo/auth/v1/login
Example response:
{"user":2,"application":null,"token":"ee0b44835f52cfe8a53c46f963f9badb2cc8eaa9","identifier":"ZeySDK","expdate":null}
As a response, you will receive the authentication token. You can store this token in a local settings file, so that the user only needs to login once.
No matter if you want to sync an existing application or create a new one, the first thing you do is retrieving the application's current state.
Example with CURL:
curl -H 'Authorization: Bearer ee0b44835f52cfe8a53c46f963f9badb2cc8eaa9' https://cloud.zeyos.com/sdkdemo/sdk/v1/sync/mydemoapp
If the app does not exist, the server will return status code 404
.
Otherwise, the result will look like this:
{
"lastmodified": 1511964548,
"name": "My Demo App",
"version": 10200,
"vendor": "",
"defaultsettings": null,
"settings": null,
"settingscode": "",
"usersettingscode": "",
"services": {
"label_print": {
"lastmodified": 1511964548,
"name": "Label Printout",
"type": 1,
"entity": "",
"schedule": 0,
"interval": 1,
"url": "",
"code": "a93b0ad3b593c83af31373a37bfe8bdd"
}
},
"resources": {
"label_data": {
"lastmodified": 1511968815,
"name": "Test Data",
"mimetype": "application/json",
"code": ""
}
},
"weblets": {
"dialog": {
"lastmodified": 1511964548,
"name": "Labeldruck",
"view": "inventory.details_item",
"type": 3,
"width": 380,
"height": 330,
"url": "",
"code": "4aa28b2e01ad13154a21fa937eea711b",
"langaliases": "{}",
"svgpath": "",
"color": ""
}
}
}
The next thing you do is is compare the lastmodified
date as well as the code
hash with your local files. Based on the differences you perform prepare the sync operation.
Now is where it get's interesting. Let's say, based on previous demo app, that we want to
- add a new service called
test.ixml
- remove the resource
label_data
- retrieve the weblet
dialog
And yes, we can do all these things in one operation!
{
"services": {
"test": {
"GET": true,
"name": "Label Printout",
"type": 1,
"entity": "",
"schedule": 0,
"interval": 1,
"url": "",
"code": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<!DOCTYPE ixml SYSTEM \"http://www.ixmldev.com/schema/ixml.dtd\">\r\n<ixml>\r\n\r\n<output>Hello world</output>\r\n\r\n</ixml>"
}
},
"resources": {
"label_data": {
"DELETE": true
}
},
"weblets": {
"dialog": {
"GET": true
}
}
}
see https://app.swaggerhub.com/apis/zeyos/auth/v1
POST: /auth/v1/login
name=<username/email>&password=<password>&identifier=<identifier>
(The value for the parameter identifier
is ZeySDK
)
{
"token": "..."
}
GET: /auth/v1/logout
Authorization: Bearer <token>
Checks, if a session exists
- HEAD:
/auth/v1
- GET:
/auth/v1
- GET:
/auth/v1?access=1
Authorization: Bearer <token>
{
"user": User ID,
"contact": Contact ID,
"name": Username,
"email": E-Mail
}
If param ?access=1
is set, you will receive additional session information:
{
"user": User ID,
"contact": Contact ID,
"name": Username,
"email": E-Mail,
"admin": true|false,
"nopublic": true|false,
"groups": {
"My Group": true|false // Writable,
...
},
"permissions": {
"messages": true|false // Writable,
...
}
}
see https://app.swaggerhub.com/apis/zeyos/sdk/v1#/sync-app/getApplication
GET: /sdk/v1/sync/<appidentifier>
Retrieves the application details - usually called before performing a sync.
Authorization: bearer <token>
{
"lastmodified":1504678734,
"name":"Data Retrieval",
"version":10000,
"vendor":"ZeyOS, Inc.",
"defaultsettings":"99914b932bd37a50b983c5e7c90ae93b",
"settings":null,
"settingscode":"d41d8cd98f00b204e9800998ecf8427e",
"usersettingscode":"d41d8cd98f00b204e9800998ecf8427e"
"services":{
"net.zeyon.zeyreports-1000.api":{
"lastmodified":1504678734,
"name":"Data Retrieval API",
"type":1,
"entity":"",
"schedule":0,
"interval":1,
"url":"",
"code":"ef9e3d7bd204962b3ec675b8465adb9f"
},
...
},
"resources":{
"net.zeyon.zeyreports-1000.view.Components":{
"lastmodified":1504678734,
"name":"Data Retrieval View Components",
"mimetype":"application/json",
"code":"8f0025aef7a96c9fb3f5f5dd934ba2b3"
},
...
}
}
When getting the application details, some field properties can be quite large. To reduce traffic, only the MD5 hash of the property value is being returned (or null if the value is empty). This is sufficient, because the GET request is only supposed to deliver information on the remote application state in order to compare it with the local application state.
This affects the following properties:
settings
defaultsettings
settingscode
usersettingscode
code
(for services, resource and weblets)
see https://app.swaggerhub.com/apis/zeyos/sdk/v1#/sync-app/setApplication
PATCH: /sdk/v1/sync/<appidentifier>
Authorization: Bearer <token>
The body includes the application settings as well as the individual resources. There are two "magic" parameters: GET
and DELETE
.
GET
will return the current/updated node state on the server. If not specified, only lastmodified
will be returned.
DELETE
will remove the asset on the server - be careful!
Retrieve application settings from the server:
{
"GET": true
}
Result:
{
"lastmodified":1504678734,
"name":"Data Retrieval",
"version":10000,
"vendor":"ZeyOS, Inc.",
"defaultsettings":"echte settings",
"settings":null,
"settingscode":"echter code",
"usersettingscode":"echter code"
}
Update the application name on the server and retrieve the updated server state:
{
"GET":true,
"name":"Data Retrieval 2"
}
Result:
{
"lastmodified":1504678737,
"name":"Data Retrieval 2",
"version":10000,
"vendor":"ZeyOS, Inc.",
"defaultsettings":"ECHTE SETTINGS",
"settings":null,
"settingscode":"ECHTER CODE",
"usersettingscode":"ECHTER CODE"
}
Update a service name:
{
"services": {
"check_contact": {
"name": "Check Contact Service"
}
}
}
Result:
{
"lastmodified": 1504678737,
"services": {
"check_contact": {
"lastmodified": 1504678737
}
}
}
Retrieve the service details:
{
"services": {
"check_contact": {
"GET": true
}
}
}
Result:
{
"lastmodified": 1504678734,
"services": {
"check_contact": {
"lastmodified": 1504678734,
"name": "Check Contact Service",
"type": 1,
"entity": "",
"schedule": 0,
"interval": 1,
"url": "",
"code": "<ixml> ... REAL CODE"
}
}
}
Update the service name on the server and retrieve the details:
{
"services":{
"check_contact":{
"GET": true,
"name": "New Service Name"
}
}
}
Result:
{
"lastmodified": 1504678737,
"services":{
"check_contact": {
"lastmodified": 1504678737,
"name": "New Service Name",
"type": 1,
"entity": "",
"schedule": 0,
"interval": 1,
"url": "",
"code": "<ixml> ... REAL CODE"
}
}
}
Remove a service
{
"services":{
"check_contact":{
"DELETE": true
}
}
}
Result:
{
"lastmodified": 1504678734
}
Combined example:
- Retrieving the current state of one service,
- while removing a weblet and
- updating the application's defaultsettings
- adding a new PDF resource
When uploading non-text content, you need to base64-encode the content. In order to determine if base64 encoding is necessary, you can use the following regular expression on the mimetype:
'#^text/|^(?:application/(?:javascript|json)|message/rfc822)$|[/+]xml$#D'
Request:
{
"defaultsettings": "{...}" // JSON string!
"services":{
"helper": {
"GET": true
}
},
"weblets": {
"demo_popup": {
"DELETE": true
}
},
"resources": {
"template": {
"name": "PDF Base Template",
"mimetype": "application/pdf",
"code": base64.encode(filecontents)
}
}
}
Result:
{
"lastmodified": 1504678737,
"services":{
"helper": {
"lastmodified": 1504678737,
"name": "Data Retrieval API 2",
"type": 1,
"entity": "",
"schedule": 0,
"interval": 1,
"url": "",
"code": "<ixml> ..."
}
},
"weblets": {
"demo_popup": {
"lastmodified": 1504678737
}
},
"resources": {
"template": {
"lastmodified": 1504678737
}
}
}
DELETE: /sdk/v1/sync/<appidentifier>
Authorization: Bearer <token>
see https://app.swaggerhub.com/apis/zeyos/sdk/v1#/run/run
PUT: /sdk/v1/run?identifier=...&appidentifier...
When developing and debugging an application is becomes necessary to execute a script on the server and check the console output.
The parameters identifier
and appidentifier
are optional, but should be submitted nevertheless since they define the runtime context.
Authorization: Bearer <token>
{
"comp" : compile time in seconds with microsecond fraction,
"exec" : execution time sin seconds with microsecond fraction,
"memory" : peak memory usage in bytes,
"size" : Byte size of unescaped output binary data,
"engine" : "iXML" oder "Zymba",
"version" : iXML/Zymba version number, z.b. 10000,
"error" : 'Error message',
"output" : \addcslashes('Output Binary Data', "\0..\10\13..\37\177..\377"),
"debug" : \addcslashes('Debug Output Binary Data', "\0..\10\13..\37\177..\377")
}
Note: \addcslashes('...', "\0..\10\13..\37\177..\377")
is taking care of Non-UTF8 Output (e.g. PDF) so that they can be submitted correctly via JSON.