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:
- Click the Authorize button at the top of the page.
- Enter an API key in either the
headerAuth
orqueryAuth
box. - Click the Authorize button.
- 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:
- The API key specified in the request is not valid.
- The request was made from an IP address range that the API key is not authorized for.
- The request was made to an API endpoint that the API key is not authorized for.
- The institution is not authorized to use the API.
- 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:
- 30 requests per second, and
- 400 requests per minute.
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:
- 5 seconds
- 10 seconds
- 20 seconds
- 40 seconds
- 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.