Standard API Graph Template

Building APIs in Kitewheel is fast, simple and scalable. Any graph with an API listener can be called as an API. Kitewheel is best used for RPC style APIs where users send an operation query parameter which is used to decide which subgraph to execute. This template provides a quick jumpstart to providing a standard API.

Often, clients have many systems with their own APIs in different locations; maintaining access/ networking permissions can become tedious over time. Implementing a Kitewheel API as a master API means the client only has to maintain a single point of access to both the Kitewheel API and the existing APIs whilst providing flexibility, scalability and functionality.

Example RPC API:

GET https://api.kitewheel.com/api/v1/listener/{listenerId}?op=testKitewheel   or  POST https://api.kitewheel.com/api/v1/listener/{listenerId} Body: {"op":"testKitewheel"}

Example response:

{"meta":{"code":200,"messages":["Kitewheel is listening"]}}

It is not currently possible to implement Kitewheel as a RESTful API however our experience has shown that the RPC style has advantages over REST, see here.

Your calls must be structured as such:

  1. GET calls supplied with query parameters e.g. GET https://api.kitewheel.com/api/v1/listener/{listenerId}?op=testKitewheel
  2. POST calls supplied with body text e.g. POST https://api.kitewheel.com/api/v1/listener/{listenerId} Body: {"op":"testKitewheel"}
    1. POST calls will ignore any query parameters

The user specifies an 'operation' to be carried out e.g. 'getTransactionById'.  This operation may have 'options' that are either mandatory or optional to complete the request e.g. 'transactionId' is needed to lookup a transaction, it is optional to request 'enhancedInfo' as it is set to false by default.

operations
{"operations": {
		"getTransactionById": {
			"mandatory": ["transactionId"],
			"optional": ["enhancedInfo"]
		},
		"getTransactionsByPeriod": {
			"mandatory": ["startTs", "endTs"],
			"optional": ["maxRecords", "orderBy"]
		},
		"getOperations":{
			"mandatory": [],
			"optional": []
		},
		"testKitewheel": {
			"mandatory": [],
			"optional": []
		}
	}
}
options
{"options": {
		"transactionId": {
			"description": "An alphanumeric string",
			"type": "string",
			"regExp": "^[-.@0-9a-zA-Z]+$",
			"schemaLocation": "transactionId"
		},
		"startTs": {
			"description": "Time format='YYYY-MM-DD HH:MM:ss.SSS'  ms are optional",
			"type": "datetime",
			"validateTs": true,
			"regExp": "^[0-9]{4}-[0-9]{2}-[0-9]{2}\\s[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{3})?$",
			"schemaLocation": "request.startTs"
		},
		"endTs": {
			"description": "Time format='YYYY-MM-DD HH:MM:ss.SSS'  ms are optional",
			"type": "datetime",
			"validateTs": true,
			"regExp": "^[0-9]{4}-[0-9]{2}-[0-9]{2}\\s[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{3})$",
			"schemaLocation": "request.endTs"
		},
		"maxRecords": {
			"description": "Integer - maximum limit",
			"type": "numeric",
			"regExp": "^(\\d{1,2})$",
			"min": 1,
			"max": 100,
			"schemaLocation": "request.maxRecords",
			"defaultValue": "1"
		},
		"orderBy": {
			"description": "Integer - maximum limit",
			"type": "numeric",
			"regExp": "^(asc|desc)$",
			"schemaLocation": "request.orderBy",
			"defaultValue": "desc"
		},
		"enhancedInfo": {
			"description": "Boolean true/false",
			"type": "boolean",
			"regExp": "^(true|false)$",
			"schemaLocation": "request.enhancedInfo",
			"defaultValue": "false"
		}
	}
}


Package contents

Setup 

  • Deploy the API graph template to create all the required Kitewheel resources (includes AppParams ( please follow the steps for setting up AppParams)
  • OPTION - Choose 1 of the methods below:
    • Set your apiSpec by using the setApiSpec javascript in the apiEndpoints subgraph - easy to use and maintain
      • Edit 'setApiSpec' javascript to reflect the operations and options of your api.
    • Set your apiSpec and store in appParams in your database - slightly more difficult however enables dynamic apiSpec to be updated without creating a new release
      • Insert the following record called 'apiSpec' into appParams.
        • Note the apiSpec json has been minified and then escaped using this online tool
        • Minifying means you will not need to escape the new line characters
        • The escape allows you to insert it into SQL
        • When you wish to edit, you can copy straight from MySQL however you will need to minify and escape again.
INSERT INTO appParams
(paramKey,paramValue,paramType,description)
VALUES
('apiSpec',
"{\"operations\":{\"getTransactionById\":{\"mandatory\":[\"transactionId\"],\"optional\":[\"enhancedInfo\"]},\"getTransactionsByPeriod\":{\"mandatory\":[\"startTs\",\"endTs\"],\"optional\":[\"maxRecords\",\"orderBy\"]},\"getTransactionsSummary\":{\"mandatory\":[],\"optional\":[\"maxRecords\",\"orderBy\"]},\"getOperations\":{\"mandatory\":[],\"optional\":[]},\"testKitewheel\":{\"mandatory\":[],\"optional\":[]}},\"options\":{\"transactionId\":{\"description\":\"An alphanumeric string\",\"type\":\"string\",\"regExp\":\"^[-.@0-9a-zA-Z]+$\",\"schemaLocation\":\"transactionId\"},\"startTs\":{\"description\":\"Time format='YYYY-MM-DD HH:MM:ss.SSS'  ms are optional\",\"type\":\"datetime\",\"validateTs\":true,\"regExp\":\"^[0-9]{4}-[0-9]{2}-[0-9]{2}\\\\s[0-9]{2}:[0-9]{2}:[0-9]{2}(\\\\.[0-9]{3})?$\",\"schemaLocation\":\"request.startTs\"},\"endTs\":{\"description\":\"Time format='YYYY-MM-DD HH:MM:ss.SSS'  ms are optional\",\"type\":\"datetime\",\"validateTs\":true,\"regExp\":\"^[0-9]{4}-[0-9]{2}-[0-9]{2}\\\\s[0-9]{2}:[0-9]{2}:[0-9]{2}(\\\\.[0-9]{3})$\",\"schemaLocation\":\"request.endTs\"},\"maxRecords\":{\"description\":\"Integer - maximum limit\",\"type\":\"numeric\",\"regExp\":\"^(\\\\d{1,2})$\",\"min\":1,\"max\":100,\"schemaLocation\":\"request.maxRecords\",\"defaultValue\":\"1\"},\"orderBy\":{\"description\":\"Integer - maximum limit\",\"type\":\"numeric\",\"regExp\":\"^(asc|desc)$\",\"schemaLocation\":\"request.orderBy\",\"defaultValue\":\"desc\"},\"enhancedInfo\":{\"description\":\"Boolean true/false\",\"type\":\"boolean\",\"regExp\":\"^(true|false)$\",\"schemaLocation\":\"request.enhancedInfo\",\"defaultValue\":\"false\"}}}",
'json',
'The apiSpec detailing operations and their options');

Using  

  1. Create the API graph from the 'API (RPC)' graph template
  2. Make a note of the API listener id
  3. Deploy the API graph
  4. Test the API using the following call: 
    1. GET https://api.kitewheel.com/api/v1/listener/{your_listener_id}?op=testKitewheel
    2. Expected response: {"meta":{"code":200,"messages":["Kitewheel is listening"]}}
  5. This shows that Kitewheel is listening and able to understand your request.
  6. To add graph endpoints (example 'getProfileById'):
    1. Add an entry to the JSON object appParams.apiSpec.operations in the appParams table as follows:
      1. "getProfileById": {
        			"mandatory": [],
        			"optional": []
        		}
    2. Specify any mandatory options, for example getProfileById would require an 'id' value to be sent. Specify any optional options e.g. an option to fetch enhanced data about the profile using an 'enhancedProfile' value to be sent.

      1. "getProfileById": {
        			"mandatory": ["profileId"],
        			"optional": ["enhancedProfile"]
        		}
    3. Specify the appParams.apiSpec.options criteria. These are the rules carried out to validate the options sent e.g. to look up a profile by id, you need an ID value!

      1. "profileId": {
        				"description": "An alphanumeric string",
        				"type": "string",
        				"regExp": "^[-.@0-9a-zA-Z]+$",
        				"schemaLocation": "profile.pId"
        			}

        This object contains: 

        1. A short description of the object
        2. The option value type e.g. string, integer, number, boolean, object
        3. A regular expression to validate the option value
        4. A schema location - e.g. if the value is to be moved from one field to another within the {schema}.transaction object, perhaps a common schema location. Here the value will be copied from 'profileId' to '{schema}.profile.pid'
      2. "enhancedInfo": {
        				"description": "Boolean true/false",
        				"type": "boolean",
        				"regExp": "^(true|false)$",
        				"schemaLocation": "request.enhancedInfo",
        				"defaultValue": "false"
        			}

        This object contains:

        1. A short description of the object
        2. The option value type e.g. string, integer, number, boolean, object
        3. A regular expression to validate the option value
        4. A schema location - e.g. if the value is to be moved from one field to another within the {schema}.transaction object
        5. A default value if the option is not provided
    4. Update decideApiEndpoint.js when specifying a new option criteria*


*more documentation to follow. For now, please contact support@kitewheel.com with subject 'How to expand API template'.

Examples 

https://api.kitewheel.com/api/v1/listener/{your_listener_id}?op=testKitewheel

https://api.kitewheel.com/api/v1/listener/{your_listener_id}?op=getOperations

Possible Issues

Things that are likely to go wrong:

  • Errors with decideApiEndpoint.js
    • Invalid JSON. It is important that the apiSpec is valid JSON. When updating the apiSpec, validate it using a json validator e.g. https://jsonformatter.curiousconcept.com/
    • apiSpec is not valid. Please ensure the operation has been specified with mandatory and optional options
    • Ensure appParams and appParams.apiSpec exists 
  • Errors with apiEndpoints graph
    • The operation is specified in the apiSpec however there is no branch or no sub graph for it

Privacy Policy
© 2022 CSG International, Inc.