Skip to content
marstone edited this page Aug 13, 2025 · 25 revisions

Table of Contents

Interface

GET /users  @returns Response<User>
GET /depts  @returns Response<Dept>
GET /posts  @returns Response<Post>
GET /occupies  @returns Response<Occupy>  
  NOTICE: the 4 URIs could be in any other forms but "users"/"depts"/"posts"/"occupies" must exist and be the only difference. 
  * eg. http://example.com/get_users_since (and /get_depts_since, etc.)

Parameters

Name Type Explained
timestamp long incremental unix timestamp(*)
verbose boolean default to false, returns more fields (marked as 'verbose-field' in each data struct)

(*)timestamp

    • unix timestamp(seconds from 1970/01/01), only return entities that last update >= timestamp
    • each interface could be incremental or not
    • if implementation can't return incremental results, just bypass the parameter, and please make sure all returned entities[i].timestamp is null

Data struct

Response<T>

{
    "errno": {int},          // 0 for success, else for failed
    "error": {string},       // if failed, user friendly error message
    "entities": List<T>,     
    "total": {int}           // nullable, total entity count for pagination. 
}

base attributes of T

{
    "tags": {string},        // sync only if not null. @see https://github.com/infoplus/canvas-docs/wiki/Tags
    "meta": {string},        // @see Label in @see https://github.com/infoplus/canvas-docs/wiki/Tags
    "description": {string}, 
    "timestamp": {long},     // only required for INCREMETAL sync. last update time for the entity 
    "disabled": {boolean},   // only required for INCREMETAL sync
}

User

{ 
    "account": {string},          // not null 
    "accountFriendly": {string},  // nullable, used as an alternative & for display only. since 2022/01
    "openid": {string},           // nullable, used for migration only, since 2022/01 
    "name": {string},             // not null 
    "email": {string},
    "phone": {string},
    "cardType": {string},      // verbose-field. (cardType:cardCode) identifies an unique person
    "cardCode": {String},      // verbose-field, as above
}

Dept

{ 
    "organizeId": {string},       // not null 
    "organizeName": {string},     // not null 
    "parentOrganizeId": {string}, // nullable    
    "independent": {boolean},     // true for top-level depts. sometimes parent=null is only adequate
    "index": {integer},           // used by sorting, in DESC order, "NULL == 0". since 2025/08
}

Post

{ 
    "postCode": {string},   // not null 
    "postName": {string},   // not null 
    "parentCode": {string}, // nullable, parent post code, since 2022/01
    "formal": {boolean},    // true for triple of this post to mark a user's "official" dept  
    "index": {integer},     // used by sorting, in DESC order, "NULL == 0". since 2025/08
    "bizTypes": [{          // business types(refer to code.name) that related to this posts 
       "bizType": {string}
     }],
}

Occupy

{ 
    "account": {string},    // not null
    "postCode": {string},   // not null
    "deptCode": {string},   // not null 
    "userCode": {string},   // nullable, student number or any other numbers that corresponding to his/her post.
    "index": {integer},     // used by sorting, in DESC order, "NULL == 0". since 2018/07
    // the 4th dimension for triple, added since 2020/03/02 
    "bizes": [{            // not required. NOTICE "null" is not acceptable for "Array"(see http://json.org/)
      "bizType": {string},     // business type, better pairs with a code.name
      "bizCode": {string}      // business code, better pairs with a code item.code
    }]
    
}
Clone this wiki locally