This document provides an overview of the XenDirect API, links to helpful resources, and code samples intended for the developers of new API clients.
For additional information about API endpoints, request and response formats, refer to the Reference Documentation section.
Before you can begin with the XenDirect API, you must be a licensed API user.
There are two license levels to choose from:
For more information on purchasing an API license, contact Xenegrade Support, support@xenegrade.com.
To obtain an authentication token for access to the XenDirect API, your server must first authenticate using your API Key and organization ID.
Authentication requests are POSTed to the http://api.xendevelop.com/v2/authentication
endpoint.
For more details, refer to the AuthenticationResource documentation.
If you wish to access the API directly from a web browser, your server must proxy all requests to the API. Your application would be responsible for adequately protecting users' access to data.
Your API Key must be kept secure and treated with the same care as any other password.
Your initial API key along with an "Organization ID" will be provided to you when you acquire an API license.
You can change your API key at any time from within the XenDirect application.
An authentication token is a signed data packet containing claims about the API user's identity and access rights. Tokens are formatted according to the JSON Web Token (JWT) standard, a format that is commonly associated with the OAuth 2.0 standard.
Tokens are transferred from client to server in the "Authorization" HTTP header using the "Bearer" scheme.
Example: Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9…
A valid, unexpired token must be present for every call to the API. Tokens are signed by the issuing server to ensure that they have not been tampered with.
Bearer tokens have the property that the token itself provides authenticated access to the API, so long as the token is valid and unexpired. This scheme is in contrast to, for example, the HTTP "Basic" scheme which requires a user name and password to be transmitted from client to server for authentication. Bearer tokens are described in RFC6750.
Tokens are obtained through an authentication request, and expire after 30 minutes. For more details, refer to the AuthenticationResource documentation.
If you expect a client process to take longer than 30 minutes, your implementation must authenticate again before the expiration to obtain a new token. You may also handle a 401 response code from any API call by re-authenticating, and then retrying the failed call.
XenDirect API is a RESTful web service that speaks JSON. Request and response formatting loosely follows The Ion Hypermedia Type specification. The API is designed with the principles of HATEOAS in mind. In short, this means resources are best identified by their fully-qualified URL, rather than an internal database-driven ID. Parent-child relationships are also represented in the response data using hyperlinks. This is an important and powerful capability, as it allows client implementations to be responsive to structural changes in the API without breaking. A well-crafted client relies more on an understanding of the hypermedia protocol, and uses the metadata provided by the API to infer relationships. A more brittle (but in some ways, simpler) client relies on a direct “out-of-band” knowledge of the structural relationships in the data, which are subject to change.
All requests and responses use the application/json
media type.
For all resource actions, route parameters such as resource IDs are part of the resource URL.
Additional parameters for GET actions are appended to the URL query string.
POST and PUT actions send additional parameters in the JSON-encoded request body.
Note: POST and PUT requests must use application/json
encoding.
Do not make requests using the application/x-www-form-urlencoded
or multipart/form-data
encodings.
Starting with v2, all resource responses contain extra metadata, including fully-qualified links to related resources. Resources are divided into two categories, instance resources (often referred to as just “resources”), and collection resources.
meta
property.items
array, each of which is uniquely identifiable as an instance resource.
Collection resources can be identified by the presence of "rel":["collection"]
in the meta
property.
Collections include the additional metadata property itemCount
.
totalItemCount
, offset
, limit
, and hyperlinks first
, last
, next
and previous
which can be used to easily iterate through paged data.
Pagination can be controlled for any paged collection resource throughout the system using _offset
and _limit
request parameters.
using System;
using System.Net;
using System.Text;
using Newtonsoft.Json;
namespace ExampleApp
{
class Program
{
static void Main(string[] args)
{
var reqObj = new {
apiKey = "password", // TODO: read password from a secure source
organizationId = 12345
};
string jsonReq = JsonConvert.SerializeObject(reqObj);
using (var client = new WebClient())
{
client.Encoding = Encoding.UTF8;
client.Headers.Add("Content-Type", "application/json");
// authenticate
var resp = client.UploadData(
"http://api.xendevelop.com/v2/authentication",
"POST",
Encoding.UTF8.GetBytes(jsonReq));
dynamic auth = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(resp));
Console.WriteLine(JsonConvert.SerializeObject(auth));
Console.WriteLine("Press any key to close...");
Console.ReadKey(true);
}
}
}
}
var request = require("request");
request = request.defaults({ baseUrl: "http://api.xendevelop.com/v2" });
// authenticate
request.post(
{
url: "authentication",
body: {
apiKey: "password", // TODO: read password from a secure source
organizationId: 12345
},
json: true
},
function (error, response, auth) {
console.log(auth);
});
using System;
using System.Net;
using System.Text;
using Newtonsoft.Json;
namespace ExampleApp
{
class Program
{
static void Main(string[] args)
{
var reqObj = new {
apiKey = "password", // TODO: read password from a secure source
organizationId = 12345
};
string jsonReq = JsonConvert.SerializeObject(reqObj);
using (var client = new WebClient())
{
client.Encoding = Encoding.UTF8;
client.Headers.Add("Content-Type", "application/json");
// authenticate
var resp = client.UploadData(
"http://api.xendevelop.com/v2/authentication",
"POST",
Encoding.UTF8.GetBytes(jsonReq));
dynamic auth = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(resp));
// get courses
client.Headers.Add("Authorization", auth.access_token.Value);
client.QueryString.Add("_limit", "1");
resp = client.DownloadData("http://api.xendevelop.com/v2/courses");
dynamic courses = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(resp));
Console.WriteLine(JsonConvert.SerializeObject(courses));
Console.WriteLine("Press any key to close...");
Console.ReadKey(true);
}
}
}
}
var request = require("request");
request = request.defaults({ baseUrl: "http://api.xendevelop.com/v2" });
// authenticate
request.post(
{
url: "authentication",
body: {
apiKey: "password", // TODO: read password from a secure source
organizationId: 12345
},
json: true
},
function (error, response, auth) {
if (auth.access_token) {
// get courses
request.get({
url: "courses",
qs: {
_limit: 1
},
headers: {
Authorization: auth.access_token
}
},
function (error, response, courseData) {
console.log(courseData);
});
}
});
XenDirect API versioning follows the rules of Semantic Versioning.
Given a version number MAJOR.MINOR.PATCH, increment the:Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backwards-compatible manner, and
- PATCH version when you make backwards-compatible bug fixes.
MAJOR version increments are given a new URL root (e.g. http://api.xendevelop.com/v1/, http://api.xendevelop.com/v2/), since MAJOR changes are likely to break existing client implementations.
A client implementation must target a single MAJOR version. MINOR and PATCH level updates are released on an ongoing basis, and will not break well-designed client implementations. It is not possible to target specific MINOR or PATCH revisions. Existing clients benefit immediately from bug fixes and new features released under their targeted MAJOR version.
MAJOR versions marked as deprecated receive no further MINOR level updates. PATCH level updates to deprecated versions are possible, but rare. Clients targeting a deprecated API version should be upgraded to the latest release as soon as possible. Upgrades must be completed prior to the end-of-life date of the deprecated version in order to avoid a service outage.