Introduction

The Engage API is a RESTful API for retrieving and managing data in your Engage site. The API follows standard REST practices. It accepts JSON request bodies, returns JSON responses, and uses standard HTTP response codes, authentication, and verbs.

The Engage API supports both a test mode and a live mode. Test mode does not affect your live data, while live mode does. The API key used to authenticate the request determines whether the request is live mode or test mode.

Authentication

Query String Authentication Example

curl -X GET \
  --header 'Accept: application/json' \
  'https://engage-api.campuslabs.com/api/v3.0/finance/account?key=esk_test_3ef94b252b22047586dc53307a10580e'
using RestSharp;

var request = new RestRequest("v3.0/finance/account", Method.GET)
    .AddQueryParameter("key", "esk_test_3ef94b252b22047586dc53307a10580e");

var client = new RestClient("https://engage-api.campuslabs.com/api");
var response = await client.ExecuteTaskAsync(request);

Console.WriteLine(response.Content);
import urllib.request

baseUrl = 'https://engage-api.campuslabs.com/api'
apiKey = 'esk_test_3ef94b252b22047586dc53307a10580e'

url = baseUrl + '/v3.0/finance/account' + '?key=' + apiKey
headers = {'Accept': 'application/json'}
req = urllib.request.Request(url, headers=headers, method='GET')

with urllib.request.urlopen(req) as response:
    json = response.read().decode('utf-8')
    print(json)

Request Header Authentication Example

curl -X GET \
  --header 'Accept: application/json' \
  --header 'X-Engage-Api-Key: esk_test_3ef94b252b22047586dc53307a10580e' \
  'https://engage-api.campuslabs.com/api/v3.0/finance/account'
using RestSharp;

var request = new RestRequest("v3.0/finance/account", Method.GET)
    .AddHeader("X-Engage-Api-Key", "esk_test_3ef94b252b22047586dc53307a10580e");

var client = new RestClient("https://engage-api.campuslabs.com/api");
var response = await client.ExecuteTaskAsync(request);

Console.WriteLine(response.Content);
import urllib.request

baseUrl = 'https://engage-api.campuslabs.com/api'
apiKey = 'esk_test_3ef94b252b22047586dc53307a10580e'

url = baseUrl + '/v3.0/finance/account'
headers = {'Accept': 'application/json', 'X-Engage-Api-Key': apiKey}
req = urllib.request.Request(url, headers=headers, method='GET')

with urllib.request.urlopen(req) as response:
    json = response.read().decode('utf-8')
    print(json)

The Engage API uses API keys to authenticate requests. You can view and manage your Engage site's API keys via the API Keys page in the Admin section of your Engage site.

There are two kinds of API keys that you can use: test mode keys, and live mode keys. Test mode keys have an esk_test_ prefix and cannot be used to change data in your Engage site. Live mode keys have an esk_live_ prefix and API requests made with these keys will modify data in your Engage site.

Authentication to the API is performed via a query string parameter or a request header value. To use query string authentication, include a key parameter on every request and provide your API key as the value. Alternatively, you can send your API key as the value of the X-Engage-Api-Key header on every request. You do not need to specify both.

All API requests must be made over HTTPS. Requests made over HTTP will automatically revoke your API key and a new one will need to be generated before any more requests can be made.

Creating API Keys

API keys can be created by navigating to the API Keys page in the Admin section of your Engage site as an All Access administrator.

API keys have both a name and a description which can be used to describe what a key is used for. Since API keys have full access to various pieces of data within your Engage site, they should be as restrictive as possible and shared only with those who need them.

API keys can be restricted in various ways to increase security. Those restrictions are described in the following sections.

API Key Restrictions

These restrictions are detailed below and can be applied to an API key via the API Keys page in the Admin section of your Engage site.

IP Address Restriction

By default, API keys are restricted to only work for requests coming from a specific IP address or IP address range in order to increase security. If a request is made from an IP address that does not match the restriction, the request will fail with a 403 Forbidden response.

Method & Endpoint Permissions

API keys can be restricted to only work for specific HTTP methods and specific endpoints. If a request is made to an endpoint or uses an HTTP method that the key is not allowed to use, the request will fail with a 403 Forbidden response.

Endpoints

Documentation for all available endpoints is available in Swagger format.

Simple tests can be performed against API endpoints by using Swagger UI to view the API reference documentation. To specify an API key for Swagger UI to use:

  1. Click the Authorize button at the top of the page.
  2. Enter an API key in either the headerAuth or queryAuth box.
  3. Click the Authorize button.
  4. Close the modal window.

Once an API key has been set up in Swagger UI, the "Try it out" buttons for each endpoint will allow you to make requests against your Engage site's API and see the results directly in your browser.

You can also import the Swagger JSON into Postman in order to build requests and translate them into the programming language of your choice.

Pagination

Example Request

curl -X GET \
  --header 'Accept: application/json' \
  --header 'X-Engage-Api-Key: esk_test_3ef94b252b22047586dc53307a10580e' \
  'https://engage-api.campuslabs.com/api/v3.0/finance/transaction?skip=15&take=5'
using RestSharp;

var request = new RestRequest("v3.0/finance/transaction", Method.GET)
    .AddQueryParameter("key", "esk_test_3ef94b252b22047586dc53307a10580e")
    .AddQueryParameter("skip", "15")
    .AddQueryParameter("take", "5");

var client = new RestClient("https://engage-api.campuslabs.com/api");
var response = await client.ExecuteTaskAsync(request);

Console.WriteLine(response.Content);
import urllib.request

baseUrl = 'https://engage-api.campuslabs.com/api'
apiKey = 'esk_test_3ef94b252b22047586dc53307a10580e'

url = baseUrl + '/v3.0/finance/transaction' + '?key=' + apiKey + '&skip=15' + '&take=5'
headers = {'Accept': 'application/json'}
req = urllib.request.Request(url, headers=headers, method='GET')

with urllib.request.urlopen(req) as response:
    json = response.read().decode('utf-8')
    print(json)

Example Response

{
  "totalItems": 47,
  "items": [
    {
      "id": 4950054
    },
    {...},
    {...}
  ]
}

All "list" endpoints have a common request and response structure allowing for pagination through the endpoint's data. If no paging parameters are specified on the request, list endpoints will return the first page of 10 items.

The following request parameters can be used to facilitate pagination:

Parameter Default Purpose
take 10 Specifies the number of items to return for a single page. A maximum of 500 items can be returned per page.
skip 0 Specifies how many items should be skipped before bringing back the next page of items.

The following properties are returned on all list responses:

Property Purpose
totalItems The total number of items that match the request criteria.
items The list of items in this page of data.

Errors

Engage uses conventional HTTP response codes to indicate the success or failure of an API request. In general, codes in the 2xx range indicate that a request was successful, codes in the 4xx range indicate that invalid information was provided in the request, and codes in the 5xx range indicate an error with Engage's servers (these are rare).

Some 4xx errors can be handled programmatically and will include a response body indicating what went wrong with the request.

Status Code Meaning
400 The request contained invalid parameter values. Validation errors are returned in the response to help diagnose what invalid parameters are being sent on the request.
401 The request did not contain an API key in either the query string or as a request header.
403 The request contained an API key but it was invalid, did not have the correct permissions, or was used from an unauthorized IP address range.
404 The request was made over HTTP or attempted to access an endpoint that does not exist.
411 The request did not contain a Content-Length header. This header is required on all requests containing a body.
415 The request body was not in JSON format, or the Content-Type header did not specify application/json.
429 Too many requests have been made in a short amount of time.
500+ Something went wrong on Engage's end. (These are rare.)

Handling Errors

If an error response is returned from the server, it may be solved by following the suggestions below.

400 Bad Request

Example 400 Response

HTTP/1.1 400 Bad Request
Transfer-Encoding: chunked
Content-Type: application/json
Server: Kestrel
X-Rate-Limit-Limit: 1m
X-Rate-Limit-Remaining: 399
X-Rate-Limit-Reset: 2019-07-23T19:53:53.1532999Z
X-Powered-By: ASP.NET
Date: Tue, 23 Jul 2019 19:52:53 GMT

{"error":"The specified API version is invalid.","version":"v3.","method":"GET","endpoint":"/v3./v3.0/finance/account","ip":"0.0.0.0"}

400 errors can be fixed by checking the response body for validation errors. Once the invalid request parameters are fixed, the request can be made again.

401 Unauthorized

Example 401 Response

HTTP/1.1 401 Unauthorized
Transfer-Encoding: chunked
Content-Type: application/json
Server: Kestrel
X-Rate-Limit-Limit: 1m
X-Rate-Limit-Remaining: 399
X-Rate-Limit-Reset: 2019-07-23T19:55:12.0967331Z
X-Powered-By: ASP.NET
Date: Tue, 23 Jul 2019 19:54:12 GMT

{"error":"An API key was not specified.","version":"v3.0","method":"GET","endpoint":"/v3.0/finance/account","ip":"0.0.0.0"}

401 errors occur when an API key is not detected on the request. These can be fixed by verifying that you are sending an API key either as the key query string parameter or the X-Engage-Api-Key request header.

403 Forbidden

Example 403 Response

HTTP/1.1 403 Forbidden
Transfer-Encoding: chunked
Content-Type: application/json
Server: Kestrel
X-Rate-Limit-Limit: 1m
X-Rate-Limit-Remaining: 399
X-Rate-Limit-Reset: 2019-07-23T19:56:18.0094334Z
X-Powered-By: ASP.NET
Date: Tue, 23 Jul 2019 19:55:18 GMT

{"error":"The specified API key is not authorized to make requests from this IP address.","version":"v3.0","method":"GET","endpoint":"/v3.0/finance/account","ip":"0.0.0.0"}

403 errors occur for the following reasons:

  1. The API key specified in the request is not valid.
  2. The request was made from an IP address range that the API key is not authorized for.
  3. The request was made to an API endpoint that the API key is not authorized for.
  4. The institution is not authorized to use the API.
  5. The institution is not authorized to use the specified API endpoint.

The response body will contain a more detailed error message to help you determine which restriction caused the 403 response.

404 Not Found

Example 404 Response

HTTP/1.1 404 Not Found
Transfer-Encoding: chunked
Content-Type: application/json
Server: Kestrel
X-Rate-Limit-Limit: 1m
X-Rate-Limit-Remaining: 399
X-Rate-Limit-Reset: 2019-07-23T16:56:03.2577588Z
X-Powered-By: ASP.NET
Date: Tue, 23 Jul 2019 16:55:02 GMT

{"error":"API must be accessed over HTTPS.","version":"v3.0","method":"GET","endpoint":"/v3.0/v3.0/finance/account","ip":"0.0.0.0"}

404 errors are caused by requests being made to invalid API endpoints or requests being made over HTTP instead of HTTPS. If a 404 response is received, check the request URL and make sure it is correct. Once it has been fixed, the request can be made again.

411 Length Required

Example 411 Response

HTTP/1.1 411 Length Required
Content-Type: text/html; charset=us-ascii
Date: Tue, 23 Jul 2019 19:57:44 GMT
Connection: close
Content-Length: 344

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Length Required</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Length Required</h2>
<hr><p>HTTP Error 411. The request must be chunked or have a content length.</p>
</BODY></HTML>

411 errors are caused by requests being made without specifying a Content-Length header. If a 411 response is received, add a Content-Length header to the request and try the request again.

415 Unsupported Media Type

Example 415 Response

HTTP/1.1 415 Unsupported Media Type
Server: Kestrel
X-Rate-Limit-Limit: 1m
X-Rate-Limit-Remaining: 399
X-Rate-Limit-Reset: 2019-07-23T20:01:22.9660712Z
X-Powered-By: ASP.NET
Date: Tue, 23 Jul 2019 20:00:24 GMT
Content-Length: 0

415 errors are caused by requests being made that specify a Content-Type of any value other than application/json. The Engage API only supports JSON for requests and responses.

429 Too Many Requests

Example 429 Response

HTTP/1.1 429 Too Many Requests
Date: Tue, 23 Jul 2019 20:04:18 GMT
Content-Type: application/json
Server: Kestrel
Transfer-Encoding: chunked
Retry-After: 25

{"error":"Request rate limit exceeded."}

429 errors are caused by too many API requests being made within a short amount of time. Requests limits are as follows:

If either of these limits are broken, the API will start returning responses with a status code of 429 Too Many Requests. The response will also include the standard Retry-After response header indicating how many seconds to wait before making another request.

500+ Engage Server Errors

500 errors are caused by issues with Engage's servers. These errors cannot be fixed by changing the request. Instead, requests should be retried after a delay. Our recommendation is to retry the request five times with an exponential backoff after each retry.

For example, if a request fails, retry it using the exponential backoff equation: 2 ^ retry * 5. This formula will generate the number of seconds after each request that should be waited before attempting the request again. Using a retry value of 0 for the first retry and incrementing it by one after each retry generates the following sequence of wait times:

  1. 5 seconds
  2. 10 seconds
  3. 20 seconds
  4. 40 seconds
  5. 80 seconds

If, after five retry attempts, the request still fails, a support request may need to be made with Campus Labs Support in order to resolve the issue.

Idempotent Requests

curl -X POST \
  --header 'Accept: application/json' \
  --header 'X-Engage-Api-Key: esk_test_3ef94b252b22047586dc53307a10580e' \
  --header 'Idempotency-Key: 3494d1a7-6426-48f4-93e1-67ce3e62e2b8' \
  --header 'Content-Type: application/json' \
  -d '{"name":"Club Baseball","parentAccount":{"id":95917},"organizationId":166491}' \
  'https://engage-api.campuslabs.com/api/v3.0/finance/account'
using RestSharp;

var request = new RestRequest("v3.0/finance/account", Method.POST)
    .AddHeader("X-Engage-Api-Key", "esk_test_3ef94b252b22047586dc53307a10580e")
    .AddHeader("Idempotency-Key", "3494d1a7-6426-48f4-93e1-67ce3e62e2b8")
    .AddJsonBody(new
    {
        Name = "Club Baseball",
        ParentAccount = new
        {
            Id = 95917
        },
        OrganizationId = 166491
    });

var client = new RestClient("https://engage-api.campuslabs.com/api");
var response = await client.ExecuteTaskAsync(request);

Console.WriteLine(response.Content);
import json

baseUrl = 'https://engage-api.campuslabs.com/api'
apiKey = 'esk_test_3ef94b252b22047586dc53307a10580e'

url = baseUrl + '/v3.0/finance/account'
headers = {
    'Accept': 'application/json',
    'X-Engage-Api-Key': apiKey,
    'Idempotency-Key': '3494d1a7-6426-48f4-93e1-67ce3e62e2b8'
}
data = str(json.dumps({
    'name': 'Club Baseball',
    'parentAccount': {
        'id': 95917
    },
    'organizationId': 166491
})).encode('utf-8')
req = urllib.request.Request(url, data=data, headers=headers, method='POST')

with urllib.request.urlopen(req) as response:
    json = response.read().decode('utf-8')
    print(json)

The Engage API supports making idempotent requests in order to allow you to safely retry requests without accidentally performing the same operation twice. This is useful in case an API call is interrupted and you do not receive a response. For example, if a request to create a Finance Deposit does not return a response due to a network connection error, you can safely retry the request using the same idempotency key to guarantee that only one deposit is created.

To make an idempotent request, provide an additional Idempotency-Key header on the request.

Engage will store this idempotency key along with the response status and response body--regardless of whether it succeeded or failed. If another request is made with the same idempotency key, the original response will be returned instead of performing the operation again.

An idempotency key is a unique value generated by the client which the server uses to recognize subsequent retries of the same request. How you create unique keys is up to you, but we suggest using V4 UUIDs, or another random string with enough entropy to avoid collisions.

Keys are eligible to be removed from the system after they're at least 24 hours old, and a new request is generated if a key is reused after the original has been pruned.

All POST requests accept idempotency keys. Sending idempotency keys in GET and DELETE requests has no effect and should be avoided, as these requests are idempotent by definition.

Other Data Services

The following services are also available to support member campus data projects.

Bulk User Data Automated Import

Engage supports the creation and update of User data through a formatted flat file (.csv) import via sFTP to a directory hosted by Campus Labs. This method is the predominant and preferred approach to synchronize Engage user data with student information systems on a regular basis. Documentation for this method can be found on our support and documentation site.

Public Content Data Feeds

Engage offers RSS and iCal feeds for publicly-visible Organization News and Event listings. These feeds are configurable from the Data Sharing page in the Admin area of your Engage site and offer an easy way to syndicate public content to consuming applications.