Standard API Graph Template
  • 04 Jan 2024
  • 4 Minutes to read
  • Contributors
  • Dark
    Light
  • PDF

Standard API Graph Template

  • Dark
    Light
  • PDF

Article summary

Building APIs in Xponent is fast, simple, and scalable. Any graph with an API listener can be called as an API. Xponent 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 Xponent API as a master API means the client only has to maintain a single access point to both the Xponent API and the existing APIs while 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 Xponent 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:

  • GET calls supplied with query parameters, e.g. GET https://api.kitewheel.com/api/v1/listener/{listenerId}?op=testKitewheel
  • POST calls supplied with body text e.g. POST https://api.kitewheel.com/api/v1/listener/{listenerId} Body: {"op":"testKitewheel"}
  • 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, and 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

{"operations": {
        "getTransactionById": {
            "mandatory": ["transactionId"],
            "optional": ["enhancedInfo"]
        },
        "getTransactionsByPeriod": {
            "mandatory": ["startTs", "endTs"],
            "optional": ["maxRecords", "orderBy"]
        },
        "getOperations":{
            "mandatory": [],
            "optional": []
        },
        "testKitewheel": {
            "mandatory": [],
            "optional": []
        }
    }
}

Package contents

Setup 

  • Deploy the API graph template to create all the required Kitewheel resources (including 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 it in appParams in your database - slightly more difficult; however, it enables dynamic apiSpec to be updated without creating a new release.
      • Insert the following record called 'apiSpec' into appParams.
        • Note that the apiSpec json has been minified and 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. 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
    "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.
    "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!
"profileId": {
				"description": "An alphanumeric string",
				"type": "string",
				"regExp": "^[-.@0-9a-zA-Z]+$",
				"schemaLocation": "profile.pId"
			}

This object contains:

  • A short description of the object
  • The option value type e.g. string, integer, number, boolean, object
  • A regular expression to validate the option value
  • 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'
"enhancedInfo": {
				"description": "Boolean true/false",
				"type": "boolean",
				"regExp": "^(true|false)$",
				"schemaLocation": "request.enhancedInfo",
				"defaultValue": "false"
			}

This object contains:

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

For more information
Please contact customer support with the 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 subgraph for it.

Is it helpful? React and share your comment

Changing your password will log you out immediately. Use the new password to log back in.
First name must have atleast 2 characters. Numbers and special characters are not allowed.
Last name must have atleast 1 characters. Numbers and special characters are not allowed.
Enter a valid email
Enter a valid password
Your profile has been successfully updated.
ESC

Eddy AI, facilitating knowledge discovery through conversational intelligence