Project

General

Profile

Actions

Request and response protocol

API Server principle

The API Server is based on the RPC principle. Commands are sent to the server which process them and return responses.

The API Server is not based on the REST-FULL principle, because the feature and the coverage of the API is not limited to CRUD behavior, plus other issues not to be discussed here.
However some principles of the REST-FULL APIs are kept:
  1. HTTP protocol.
  2. No server-side state (except for authent. v0).
  3. Except for the first authentification protocol (authent. v0), authentification is not based on a session paradigm. See Authentification.
  4. No session. The server is session-less, even if the client must support a JSESSIONID cookie for performance purposes, the JSESSIONID cookie value may be changed at any time by the server or may be forgotten by the client at any time.
  5. Full-fledged GUID (TBD).

The APIs are defined by a set of possible command grouped by genre. Each API has a name which begins with the group name.
For instance you can have ctcget , ctccreate, ctcupdate, eventget, eventcreate, eventupdate where contact and event are two groups of APIs.
This is purely organisational and there are no semantics hidden behind the genre.

Each api has a given set of parameters and output a result:
  • Parameters: Each parameter has a name, a type (String,Integer,Boolean,Enum,Date,List,etc...). Each parameter may be required or optional.
    Parameters can also be of complex type such as a structure or a collection (array, map)...
  • Result: Each result is a well-defined data structure. It may be a simple type (Boolean, String, etc) or a complex structure.
  • Error: Each api may return an error instead of the result. The error is composed of a type, a code (integer) and eventually extra parameters.
    The error maybe Attended errors or Unattended errors.
    All possible Attended error codes is well-defined for each APIs whereas Unattended error codes are possible for any APIs.

API HTTP Syntax

In order to make call to the Server API, the API caller must be authentified. See Authentification.
Within the HTTP protocol, HTTP request indicates the name and the parameters of api to call. HTTP Response returned by the server contains the result of the call. Several syntax to encode the requests and the response is proposed.

Encoding: UTF8. The encoding of queryString parameters (notably in GET) is decoded by the server in UTF8. Note that this is different from the common usage and RFC that normally requires that GET parameters are encoded/decoded in ISO-8859-1.

Compression: GZIP. Because the response can be big and the network can be slow, especially on mobile network, the client MUST ask for GZIP compression for JSON. The server must return GZIPPED content in this case. Example:

Request header:
    Accept-Encoding    gzip

Response header:
    Content-Encoding    gzip

JSON RPC Syntax

The JSON RPC Syntax encode the API request within the HTTP queryString (either in GET or POST) and the result is returned in the HTTP response as a JSON document (mime application/json).

The JSON RPC Syntax is accessible through the ENDPOINT URL: http(s)://<SERVER_ADDR>/api .

The particularity of the JSON RPC Syntax is that it enables several API calls to be embedded into one HTTP request.

JSON RPC QueryString Format

Several API calls can be encoded in one request. The encoding goes like that:
  1. Each API calls is encoded by a set of parameter in the queryString.
  2. To differenciate one API call from another, the parameter is prefixed by a prefix specific to each api call.
  3. The prefix is always 3 characters, beginning with a letter and then 2 digits. The letter 'a' shall be used by default, other letters being reserved for future usage.
  4. The name of the api is defined by the queryString parameter 'call'

If no parameter aXXcall is found, the <xx> call is not considered. (xx being the command number)
There may be "holes" in <xx>, but <xx> must be a positive integer. API calls are sorted according the <xx> in ascending order.

For instance, we want to call the api ctccreate and ctcdelete to create one contact and delete another:

a01call=ctcreate&a01firstName=newContact&a02call=ctcdelete&a02contactIds=4444

Encoding types goes like that:
  • Simple types:

Simple types are : String, Boolean, Date, Integer, Long, Enum, etc...

Boolean are encoded using "true" or "false"

Date are encoded according to ISO 8601 in "Z" format. Special values for setting specific empty date is $empty. It is used for instance to remove birthday from contacts:

api?a01call=ctcupdate2&a01contactId=contact%2F42_1741&a01firstName=eeee&a01birthDate=$empty

Enum are encoded in strings, possible values are constrained. Special values "SOMETHING_ELSE" is used to manage backward compatibility. See backward-compatibility

  • Complex types:

Complex types are encoded using the . as the property separator. For instance, the device of a contact is a complex type composed of 3 properties : deviceId, deviceType and value. A parameter 'device' of type Device is encoded like that:

 device.deviceId=123&device.deviceType=MOBILE&device.value=0633445566 

  • Arrays

Arrays can be encoded in two way:

encoded either using the classic "html form" format, repeating the parameter several times. For instance in the api ctcdelete, contactIDs is an array of integer:

a02call=ctcdelete&a02contactIds=4444&a02contactIds=5555

encoded by using the . and the index within the array. For instance :
a02call=ctcdelete&a02contactIds.0=4444&a02contactIds.1=5555

The lastest method is usefull when encoding an array of complex type. For instance in ctccreate2 the parameter devices is an array of Device :
api?a01call=ctccreate2&a01firstName=coincoin&a01devices.0.deviceType=PHONE&a01devices.0.value=123&a01devices.1.deviceType=EMAIL&a01devices.1.value=toot%40x.com

Encoding empty array is possible using the special keyword $empty. Example:

api?a01call=ctcupdate2&a01contactId=contact%2F42_1741&a01firstName=eeee&a01devices=$empty

This enables you to specifically set an empty array onto an object. For instance here it is used to remove all devices from a contact.

  • HTTP Headers

HTTP headers does not transport request parameters per-se. They may be used with their original HTTP semantics. Some API use them as parameters (see wallnotification), but this usage is deprecated.

  • Media management

API parameters can be Files, Medias, byte arrays, blobs, whatever you name them. Their management is specified here: MediaManagement

JSON RPC Output

The API will respond in JSON format. The JSON structure is the following:

  1. First level in JSON is the list of apis calls performed in the http request. Key is the prefix (ie a01) and value is the result of the api.
  2. Second level is a structure containing the name of the api called under 'cn' and the corresponding result, which may be:
  1. The 'r' key indicate a success (the response).
  2. The 'ex' key indicate an error
  3. The 'un' key indicate an unattended error
  1. 'r': If the result of an API is a simple type (string, integer, boolean, ...), the 'r' element will contains "r":"<value>".
    If the result is a complex type, the 'r' element will contains "r": { ... }
  2. 'ex' and 'un': both elements share the same syntax, but indicate either an error or an unattented error. The syntax is:
        "un":{
          "un":{
            "message":"firstName or lastName must be set",
            "FiZClassId":"500" 
          }
        }
    

FizClassId represents the error code and must be used for any error management by the client. The message is indicative only.

For complex return type, a corresponding JSON structure is generated.

All JSON properties are encoded as String. Integer and boolean are encoded as "123" or "true"

Example:

We are calling 3 apis to create 3 contacts in one HTTP call. The 3rd create contact is invalid and therefore will return an error:

 api?a01call=ctccreate2&a01firstName=coincoin&a01devices.0.deviceType=PHONE&a01devices.0.value=123&a02call=ctccreate2&a02firstName=coincoin2&a02devices.0.deviceType=PHONE&a02devices.0.value=123&a03call=ctccreate&transactional=true 

The corresponding result is :

{
  "a01":{
    "r":{
      "r":{
        "contactId":"42_1200",
        "accountId":"23",
        "pictureURIs":[],
        "firstName":"coincoin",
        "displayName":"coincoin",
        "devices":[
          {
            "deviceType":"PHONE",
            "value":"123",
            "deviceId":"42_1200_1180" 
          }
        ],
        "addresses":[],
        "editable":"true" 
      }
    },
    "cn":"ctccreate2" 
  },
  "a02":{
    "r":{
      "r":{
        "contactId":"42_1201",
        "accountId":"23",
        "pictureURIs":[],
        "firstName":"coincoin2",
        "displayName":"coincoin2",
        "devices":[
          {
            "deviceType":"PHONE",
            "value":"123",
            "deviceId":"42_1201_1181" 
          }
        ],
        "addresses":[],
        "editable":"true" 
      }
    },
    "cn":"ctccreate2" 
  },
  "a03":{
    "cn":"ctccreate",
    "un":{
      "un":{
        "message":"firstName or lastName must be set",
        "FiZClassId":"500" 
      }
    }
  }
}

JSON RPC Transaction Management

Usually, transaction boundaries and transaction management is handled by the server and totally transparent to the client.

Optionally, the transaction management can be tuned by the caller:

There is some case where the caller encode several api calls in one http request and may want that all of the api calls participate in only one transaction. For instance, you may want to set-up a sign-up process that perform: log2create (create an account) and acccreatefamily (create your own family). In this case it is interesting to have a single atomic transaction context for those two apis.

In this case, the parameter "transactional=true" my be used and will use only one atomic transaction to encapsulate all api call of the current http request.

Example:

 api?a01call=ctccreate2&a01firstName=coincoin&a01devices.0.deviceType=PHONE&a01devices.0.value=123&a02call=ctccreate2&a02firstName=coincoin2&a02devices.0.deviceType=PHONE&a02devices.0.value=123&a03call=ctccreate&transactional=true 

This creates 3 contacts transactionally, but the last call is invalid (no firstname), therefore the 3 api calls are rejected.

When a transaction is rejected, an attribute "transaction":"aborted" is added in the JSON output:

{
  "a01":{
    "r":{
      "r":{
        "contactId":"42_1200",
        "accountId":"23",
        "pictureURIs":[],
        "firstName":"coincoin",
        "displayName":"coincoin",
        "devices":[
          {
            "deviceType":"PHONE",
            "value":"123",
            "deviceId":"42_1200_1180" 
          }
        ],
        "addresses":[],
        "editable":"true" 
      }
    },
    "cn":"ctccreate2" 
  },
  "a02":{
        ....
  },
  "a03":{
    "cn":"ctccreate",
    "un":{
      "un":{
        "message":"firstName or lastName must be set",
        "FiZClassId":"500" 
      }
    }
  },
  "transaction":"aborted" 
}

Note the "transaction":"aborted" at the end, indicating that both 3 apis have been actually rollbacked.

JSONP RPC Syntax

The JSONP RPC syntax is a derived syntax from JSON RPC to be used in a Javascript WEB Application context.

The purpose of this JSONP api is to return a JSON modified format of the API in order to remove the same-origin issue of Javascript applications.
See: http://en.wikipedia.org/wiki/JSONP

The JSONP RPC Syntax is accessible through the ENDPOINT URL: http(s)://<SERVER_ADDR>/api/* .

The request syntax of JSONP does not allow to have multiple api calls in one http request. However the syntax is easier:

api/<API_GENRE>/<API_NAME>?<API_PARAMETERS>&jsonp=<JSONP_REF>

JSONP_REF is the name of the JSONP function that will contain the JSON result.

Example of a create contact with firstName=coincoin and a phone device:

 api/ctc/create2?firstName=coincoin&devices.0.deviceType=PHONE&devices.0.value=060606&jsonp=myjsonpname 

The result of the JSONP is :

 <JSONP_REF>( { JSON_RESPONSE } ) 

Example:

myjsonpname(
{
  "cn":"ctccreate2",
  "feed":{
    "contactId":"42_1202",
    "accountId":"23",
    "pictureURIs":[],
    "firstName":"coincoin",
    "displayName":"coincoin",
    "devices":[
      {
        "deviceType":"PHONE",
        "value":"060606",
        "deviceId":"42_1202_1182" 
      }
    ],
    "addresses":[],
    "editable":"true" 
  }
}
)

API definition and htmlform

The server is self-generating a test page called htmlform (url is <SERVER_URL>/htmlform) and containing all APIs definition.

Examples:

Method : ctccreate2
create a contact
    a01firstName         
    a01lastName         
    a01function         
    a01gender         
    a01birthDate         
    a01pictures     + -     
    a01devices     + -     
        a01devices.0.deviceId         
        a01devices.0.deviceType         
        a01devices.0.value         
    a01adresses     + -     
    a01adresseTypes     + -     

Return : IContact

Error codes:
FizContactAlreadyExistsException    200
FizMediaQuotaExceededException    601

Below the description of the API, the list of parameters is defined, and then the return type and the possible error codes.

Updated by jerome bonnet over 13 years ago ยท 3 revisions