API Manual

Overview

The PoolPass cloud service Application Programmer Interface provides a mechanism by which you can integrate our service into your own app, web server, or other software component. We expose various well-defined RESTful service endpoints to which you make requests to over the internet via HTTP methods. As an example, you could use the API to request your facility's occupancy using an HTTP GET method and display it on your community website.

The API documentation describes how to use our API and is intended for software developers with a background in web development. We assume prior knowledge of the HTTP protocol, HTTP headers, and JSON format. This manual provides examples in various programming languages, but you can use any language you wish.

API Documentation is divided into two parts. This API manual provides the details on how to use the API service. The API Reference describes each REST method along with the required parameters and the generated responses. The API Reference is available interactively and allows you to try the methods directly from the web page. You can also download a .pdf file of the API reference.

Authentication and Security

In order to start making API calls for a specific database (account), you need both the database name and an API key. An API key is a string of numbers and letters and is associated with a PoolPass user who has access to the database. The API can be used to interact with all databases that the user has access to. You can retrieve your API key through the cloud portal on your Profile page. To add, change, or delete an API key you must contact your PoolPass account representative.

As a holder of an API key, you have unlimited control over most of your PoolPass data, and thus you must take precautions to secure that data. Compromised API keys can lead to a data breach or data loss. If you believe your API key has been compromised, contact your PoolPass account representative immediately to exchange it for a new one. Every HTTP request must be authenticated by passing the API key in the request header. Thus, the API key is visible to anyone who can read the data in transit or observe the calling code during execution. Adhere to these best practices when developing your software:

Specify your API key in the HTTP request header. Use the attribute "x-api-key".  For example, in javascript:

const opts = {method: "GET", headers: {"x-api-key": "1234abcdef"}};
const response = await fetch(uri, opts); //send the request

HTTP Methods

The PoolPass web server listens for incoming HTTP requests at a URL endpoint. Requests consist of HTTP headers and a request body, though the body may be empty. The server will process the request and reply to the client with an HTTP response code, response headers, and a response body (which also may be empty). If the request did not succeed the response will contain an error code and error message. The majority of request and response bodies will be JSON formatted data.

Return Codes

Successful HTTP requests will return code 200 OK in their response. If the request fails an error code will be returned, with a message specifying the error. Some errors are specific to the method, and are noted in the API Reference for that method. General errors that may be returned are below:

400 BAD REQUEST One or more request parameters are invalid or one or more attributes in the request body are invalid
401 UNAUTHORIZED Your API key is invalid or missing
403 FORBIDDEN Your API key does not permit access to the specified database
404 NOT FOUND The endpoint does not exist, or the requested item cannot be found in the database
409 CONFLICT Another user changed the resource before you attempted to change it, you are trying to duplicate an unique resource (such as a name, or barcode), or the operation violates some other unique constraints
429 TOO MANY REQUESTS Typically, you are exceeding your rate limit (see below), or more rarely, the database is too busy to service the request
500 INTERNAL SERVER ERROR Something went wrong with our server when processing the request, please submit a bug report if this occurs
501 NOT IMPLEMENTED Another user is editing the same resource. Typically we continue to retry but if this error occurs the resource was locked too long.
503 SERVICE UNAVAILABLE The database you are connecting to may be suspended, or our server is down. Try again shortly. If you continue to see this we may be experiencing a service outage.

Rate Limiting

In order to be equitable to all users, we limit the rate in which you can make API calls. If you exceed the rate you will receive a 429 TOO MANY REQUESTS error. If this occurs please reduce your polling rate and space out your requests. We permit an average request rate of 10 requests per second. However, you can burst your requests up to 10 in a row as fast as you can issue them, provided your overall rate does not exceed 10Hz. For instance, you might submit a request to create 10 new Members very rapidly, but you must wait to create the 11th Member until after 1 second has elapsed since the first request. Please note that if you continue to rapidly issue HTTP requests and receive 429 error codes, our server may interpret it as a denial-of-service attack and block your IP address, so please monitor for this error code.

Timezones

Some API methods need to know the timezone where your facility is located. You can include your timezone offset value in every API call, regardless of whether it is needed or not. The timezone offset value is the number of minutes west from UTC. For east offset, use a negative number.

Specify your timezone offset in the request header as "timezone-offset".  For example, in curl:

curl -H "timezone-offset: 240"   ..... //United States-New York (Eastern Daylight Savings Time, or UTC-4)
curl -H "timezone-offset: -600"  ..... //Australian Eastern Standard Time (UTC+10)

As of API version 1.7: Some methods also take an optional timezone string, which is the IANA timezone identifer such as "America/New_York". Unlike timezone offset, the timezone name takes into account local adjustments such as daylight savings time. If present, timezone takes precedence over timezone-offset.

Specify your timezone in the request header as "timezone".  For example, in curl:

curl -H "timezone: America/New_York"   ..... //United States-New York (Eastern Time, or UTC-4 or UTC-5 depending on DST)

When an API method indicates that timezone or timezone-offset are optional, then if neither are supplied, UTC is assumed.

Other HTTP Headers

Query Parameters

In the API reference required parameters are indicated with an asterisk (*). Query parameters are appended to the URL path with a ? and multiple parameters are joined by a &.

Object Models and JSON Data

Many API methods accept or return an object or array of objects. Objects are defined in JSON and are either composed of other objects, arrays, or primitive fields such as strings, integers, and booleans. When an out-of-range value is specified in a field the 400 BAD REQUEST will be returned with an explanation. String fields generally have a limit of 254 characters. Fields that support freeform text such as notes and guest register have limits of 1023 characters.

A UUID is a string of length 36 with a special format. It is comprised of 32 hexadecimal digits and 4 dashes in the pattern 8-4-4-4-12. For instance, the following string is a valid UUID: 14438955-7504-4bfa-ab31-6d89d1205c5a

JSON objects are defined in the API Reference. A discussion of some of those objects follows below.

JsonDateString

Some string fields are dates or date/time values written as text. Unless noted, these times are all local times at the location where they occurred. A JsonDateString consists of a date part optionally followed by the letter "T" and a time part.

Date Part: YYYY-MM-DD   Year, Month (01 to 12), and Day of the Month (01-31)
Time Part: HH:mm:ss     Hour (00-23), Minute (00-59), and Second (00-59)

Examples:

2021-01-15T12:00:00   (Noon on January 15, 2021)
2022-05-04            (May 4th, 2022)
2019-12-02T04:22:57   (4:22 AM and 57 seconds on December 2nd, 2019)

JsonTimeString

Some string fields represent the time of day with minute precision written as text. A JsonTimeString represents 24-hour time as HH:mm.

Examples:

07:52   (7:52 AM)
23:30   (11:30 PM)

JsonMembership and JsonMember

These objects represents a Membership and Member object respectively. Fields generally match the editable items on the Manage Memberships tab. When creating or updating an object, an undefined field is set to the default value shown in the API reference, or for strings, the default value is the empty string.

JsonMember Actions Field

The Member actions field is an integer where each bit in the number represents an action flag. If the bit is 1, the action is set and when 0, the action is cleared. You can encode and decode actions to set and read using the bitwise AND and OR operators. The table below describes the action fields:

Bit Position Action
0 (LSB) CONTACT
1 HOLD
2 PRINT
3 PROCESS
4 REDIRECT
5 REJECT
6 REVIEW
7 (MSB) SCHEDULE

Example: if a Member's action value was set to 162 (hex: A2, binary: 10100010) then the Member has the SCHEDULE, REJECT, and HOLD actions selected.

Member Image

Member Images are stored as JPEG files. There are API methods to set the image as a base64 encoded string or upload from a file. The supplied file can be PNG or JPEG format. Uploaded images are rescaled to the native storage size of 412 pixels wide by 500 pixels tall. To avoid image distortion, use an image of this size or this aspect ratio (1 : 1.21).

Synchronizing with External Changes

When using the API, be aware that an object you retrieve can later be changed by another user (or another API call) at any time. If you modify your (now older) object and update it with the server, you may overwrite a previous change. Some objects contain a lastTransaction field that can be used to avoid overwriting other users changes, making sure you are updating the most recent version of the object. The field is an incrementing integer that increases by 1 each time the object is changed. When you retrieve the object with a GET call, the lastTransaction is populated with the latest value. Supply the same value when you modify the object with a PATCH call. If the object is unchanged, the update will succeed and the returned object will contain the new lastTransaction value. If your copy of the object is stale (someone else has since modified the object) the API call will fail with error 409 CONFLICT. You should refresh the object again to get the latest changes.

The lastTransaction value can be set to null to force the change and overwrite any other changes. The field is ignored when creating new objects with POST.

Streaming Progress Response

Long running API methods stream their progress in a streaming response to keep the user informed on their progress. The method completes (either succesfully or with an error) when the the stream is finished and the connection closed. Periodically, the server emits a UTF-8 encoded string into the stream using the following format:

percentComplete;remainStatus;processingStatus;

Percent complete is an integer from 0 to 100 indicating how far along the server is processing the request. Remain status is typically a report on how much more work there is to do, and may contain an estimated time to complete. Processing status describes the amount of work done thus far. When percent complete reaches 100 no further strings will be emitted into the stream.

If an error occurs, the server emits a string into the stream and then closes it. In this case the percent complete is -1 and the format is:

-1;errorMessage;;