Getting Started

Overview

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.

Licensing

Before you can begin with the XenDirect API, you must be a licensed API user.

There are two license levels to choose from:

Full Access
Grants access to all API resources, including update capabilities for client data and client assignments.
Course-Only
Grants read-only access to scheduled course information.

For more information on purchasing an API license, contact Xenegrade Support, support@xenegrade.com.

API Key Authentication

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.

Security Precautions

Your API Key must be kept secure and treated with the same care as any other password.

  • Don't transfer the API key from your server to a web browser. Browsers should only be given the authentication token.
  • Use a secure protocol (HTTPS) to protect your authentication token.
  • Don't write your API Key directly into source code, even if the source code is only run on the server. Instead, read your password from a secure key store, a user-level environment variable, or a protected file that is not within your web root and not checked into source control.

How to Set your API Key

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.

  1. Navigate to: AdminSettingsBranch ProfileVendor Logins.
  2. Edit the XenAPI record.
  3. Set the Password field and press OK. Other fields can be left blank.

Token Based Authentication

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.

REST and HATEOAS

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.

Media Type

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.

Resource Types

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.

Instance Resource
Represents a single entity. All resources include a self-referential meta property.
Collection Resource
Represents a collection of resources contained in an 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.
Paged Collection
This is an extension of the collection resource that contains additional metadata to support pagination of data. Paged collection are used when large data sets may be represented. Additional metadata properties are 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.
Example: See the Get Courses Example for an example of accessing a paged collection resource.

Examples

Authentication

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);
  });

Get Courses

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);
      });
    }
  });

Reference Documentation

Overview

v2

v1 (Deprecated)

Versioning

XenDirect API versioning follows the rules of Semantic Versioning.

Given a version number MAJOR.MINOR.PATCH, increment the:
  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner, and
  3. PATCH version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

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.

Current Release Versions

  • v2.6.0
  • v1.0.1 (Deprecated)

Change Log

v2

v2.6.0 (2020-07-29)

  • Added: Email2 to ClientResource.

v2.5.1 (2020-06-16)

  • Fixed: PUT (Insert) Client issues with Branches and FeeGroups.

v2.5.0 (2020-04-29)

  • Added: PUT (Insert) Client to ClientCollection.
  • Added: ClientFeeGroup resource
  • Added: ClientProfile resource
  • Added: FeeGroup resource
  • Added: Branch resource
  • Added: clientMergeField to ClientModel

v2.4.0 (2017-10-11)

  • Added: ClientPasswordResource POST to verify a single client's password.
  • Added: branchID filter to ClientCollection GET.

v2.3.0 (2017-07-28)

  • Added: homePhone, mobilePhone and workPhone to ClientModel, GET and POST.
  • Fixed: Misspelled field in ClientAssignmentModel.

v2.2.0 (2017-07-12)

  • Added: minEnrollment to CourseModel.

v2.1.0 (2017-07-06)

  • Added: startDateBegin, startDateEnd, endDateBegin, endDateEnd parameters to CourseCollection resource.
  • Added: AssignmentResource and AssignmentCollection to represent ClientAssignmentModel not relative to Client
  • Added: assignments link to CourseModel
  • Deprecated: startDate parameter, available until v3. Change any usage of this parameter to startDateBegin at this time.
  • Deprecated: ClientAssignmentResource, available until v3. Change any usage of this resource to AssignmentResource at this time.

v1

v1.0.1

  • Added: courseCode and courseTitle filters to Course resource
  • Added: {organizationID} to resource paths in documentation
  • Fixed: facName and sesName orderBy options on Course resource