API Documentation
OAuth 2.0
The API uses OAuth 2.0, which is a secure standard widely used throughout the industry and an API
best practice. The API specifically uses the OAuth 2.0 password grant for authentication, with one
difference in the implementation of the auth endpoint. We allow sending an additional data element
in the POST request called domain.
Authentication Endpoint
curl --request POST \
--url http://api_url.com/api/token \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=password \
--data username=user \
--data password=pass \
--data domain=domain \
--data client_id=domain \ # (1)!
--data client_secret=mfa_code #(2)!
- You can send the domain in the client_id field if you need to conform strictly to the OAuth 2.0 spec.
- If an agency requires it, enter the multi-factor authentication code here.
The authentication endpoint is available at /api/token. The username and password fields are
required at every agency.
Agencies which use Active Directory (LDAP) authentication require the domain field be sent as
well. You may also send the domain inside the client_id field.
Agencies which require multi-factor authentication will also require you to present a one-time
passcode in the client_secret field. Your agency contact can provide you the appropriate
credentials to authenticate.
A successful response from the endpoint will provide a bearer token. This token will serve as your credentials for all of the subsequent calls you will make to the other endpoints and will last for a period of time (Default 24 hours). After your token expires, you will need to make a new authentication call and get a new bearer token to continue using the API.
Authentication Rate Limiting
The authentication endpoint is throttled for security reasons and will only respond to a small number of requests each hour.
That means if you are careless with how you authenticate and try to authenticate once per call you make, you will lock yourself out of having API access.
The API also has a global throttling limit to protect the server from DDOS and similar attacks.
- This will cut-off API access if the system is under extreme load to ensure that the ProSuite server stays online.
Bearer Token Caching
Be sure to build into your interface a process to get, re-use and replace your bearer token. Not only will this streamline the amount of traffic coming and going from the API service, but it will ensure that user credentials are rarely exposed in the traffic, so that even if the traffic were to be intercepted and somehow decrypted, the bad actor would likely only receive a bearer token-- which has already expired during the decryption window rather than getting user credentials.
Endpoint Families
The API is made up of a series of endpoints which each offers their own capabilities. For ease of use, we have separated the endpoints into their own families or groupings. A standard grouping consists of the following endpoints:
POST /searchGETPUTPOST
These methods allow for different ways to interact with the data and follow standard conventions.
GET Endpoints
- Will retrieve a specific record whose unique identifier you provide in the parameter.
POST Endpoints
- Will create a new record with the provided data elements.
PUT Endpoints
- Will replace an existing record with the new data provided.
POST /search Endpoints
- Will allow you to retrieve multiple records at once. These records will be filtered by the body elements included in the call.
POST /search Example
- For an example with the Name Search endpoint, if you include the Name body element such as Name:
"John", it will return all Name records that contain"John"in the name, such as John Smith, Dakota Johnson, John Jacobson, etc. - By applying the correct filters you can receive back just the specific record(s) you need. This will be important for performance and efficiency as if you only need two records, it's better to a do a highly filtered search and process two records, than a more generic search and process 600.
Uncommon Endpoints
The API supports the DELETE and PATCH methods for a handful of endpoint families.
DELETE Endpoints
- Will delete the record.
PATCH Endpoints
- Will merge the provided data with the existing data. Note that null or blank values provided won’t overwrite existing values on the record.
Dropdown Models
The API makes extensive use of "Dropdown Models". These are groupings of data that collectively
represent a single concept or data element but may have different formats or ways of identifying
that data. For example our Agency Dropdown model may appear as such:
"Agencies": [
{
"UniqueIdentifier": 1,
"Abbreviation": "E",
"Name": "Example",
"ORI": "MI1234500",
"RunsDispatch": false,
"DispatchedBy": "OtherAgency",
"PrimaryResponderType": null
}
],
Note that ALL of these concepts mean the same thing.
-
The
ORIis how the FBI might identify an agency and serves as a unique identifier at the federal level. -
The
Abbreviationis how the agency might be identified in day-to-day use. -
The
Nameis the formal, full name of the agency. -
The
UniqueIdentifieris how ProSuite identifies the agency. All UniqueIdentifiers are guaranteed to be unique for that data element.
Depending on the nature of your integration, you may wish to use one or more of the above concepts.
For GET and POST /search returns, we always return all available data and you can use whichever
aspects are useful for your system. For POST and PUT endpoints, you can provide one or more of
these elements and we will match to a value based on each element provided. Typically only a single
element is needed, though you may wish to check the configured values to ensure that your matching
scheme is unique. Consider the following agency configuration:

If you post an abbreviation of "MPD" we won’t know WHICH MPD you mean as there are two!
For an agency with a configuration like this, matching on only the abbreviation is going to introduce issues. You can instead match on the Agency Name (because it is unique), or both the abbreviation and the Agency Name.
# Valid dropdown for the above configuration
"Agencies": [
{
"Name": "Monroe Police Department"
}
],
For agencies with very complex configuration, it may be better to match off ORI or even the UniqueIdentifier to ensure that there are no edge cases related to the matching. For ease of development and to prevent introducing edge cases, it is recommended to review the configuration carefully and come up with a plan that allows you to match using the fewest elements that will always uniquely match to a value.
Configuration
To facilitate transparency into the values the agency uses for configurable fields, a configuration endpoint has been created which allows you to query the values in use at a given agency.
Simply enter the parameter related to the model type you are seeking values for and it will return a full list.
Multi-Agency Variability
If your interface services multiple agencies, you will want to ensure your plan to match data from your system against one of the dropdown model options can gracefully handle different configurations. If the agency MUST configure values in a certain way to interface with your system, be sure to work with them to ensure that appropriate codes are added.
Keep in mind that it is common for agencies to have dozens of interfaces with various state and local partners, so the agency may not be able to freely reconfigure every item. e.g. if a jail interface requires certain codes and you want to use different codes, that won’t work, and a more creative solution will need to be implemented.
It may also be helpful to cache or store some of these configurations in your own system. If you do this, we have a webhook that you can subscribe to in order to listen to any configuration changes, so that you can be alerted if your values ever become out of date and require an update.
Webhooks
Webhooks are a core API feature that are critical in reducing wasteful API traffic but are not yet widely used in the public safety industry. If you are not familiar with webhooks, there are many online guides that explain how to interact with them. There are also many libraries for various programming languages that let you stand up a webhook listening service with as little as a single line of code.
At the highest level, webhooks let you subscribe to get notifications when certain types of records are created or updated. You then need to call into the API to receive the related data (thereby triggering the standard auditing and authentication processes). This allows you to get the relevant content pushed to you when it is available instead of needing to check the service every 5 seconds to see if anything has changed. This will also reduce the traffic down to the exact level that is needed to get your data without any wasted calls which in turn reduces server performance burden and helps keep audit trails and troubleshooting logs crisp, which can be extremely helpful for complicated integrations.
The way our webhooks work is that you must create a subscription. Subscriptions are done at the endpoint family level. Each family offers different filter options and requires you to provide the CallBackURL for us to call your listening service. Based on the options selected, whenever a record matching the criteria is created or edited, we will send a data package to that URL which contains the UniqueIdentifier, Agency and the specific API endpoint URL to call back and get the update.
# Example JailCourtEvents Subscription (POST)
{
"CallbackURL": "http://www.example-api.com",
"BookingNumber": "IN202400001",
"CourtEventAction": {"UniqueIdentifier": 8, "Description": "Sentenced"},
}
# When inmate IN202400001 gets a sentencing hearing, your callback endpoint will receive the
uniqueidentifier of the court event which was created or changed and the URL to call in to get the update.
You will then do a GET call to get the data.
{
"CallbackURL": "http://www.example-api.com",
"CourtEventUniqueIdentifier": 1,
"Agency": {
"UniqueIdentifier": 1,
"Abbreviation": "Ex",
"Name": "ExampleAgency",
"ORI": "EA00001",
"RunsDispatch": false,
"DispatchedBy": null,
"PrimaryResponderType": "Law Enforcement"
},
}
Subscriptions can be replaced via the PUT version of the subscription webhook endpoints.
We also offer the ability to GET, POST /search and DELETE webhooks at the system level. These
system endpoints apply to all webhooks as the functions aren’t different family to family.
Please delete any test subscriptions when you are done with them. Agency Administrators can also view and delete your subscriptions from within ProSuite.
It is anticipated that webhooks will be a part of most interfaces as they are ideal for interfaces
that want to maintain real time updates or only want to grab a record at a certain point in the
process. Like POST /search calls, webhooks work best when you use appropriate filters to get down
to just the data you NEED. For example, if you are working on a CAD fire integration, you would
want to filter it to just calls with a fire responder, or just calls with an incident code that
suggests a fire occurred like CARFIRE, STRUCTFIRE, VEHFIRE etc. The better your filter, the less
data you must process and the more efficient the interface will be.
Pagination
All endpoints capable of returning multiple records (i.e. POST /search endpoints) will return no
more than 100 records at a time. This is a global cap, but agencies can lower this based on their
configuration should this be needed for performance reasons. You may also lower your own pagination
limit if desired e.g. if you wish to display 10 address suggestions, you might search for an address
and limit it to 10. This is done via the Skip and Take parameters. Take determines how many records
you want back (still subject to the global and agency caps). The skip is used for the 2nd and
subsequent calls to skip the first X records that you already reviewed.
For example, let's say there are 250 records that match your search criteria and the default 100 pagination limit is in place. On your first call you will receive records 1 to 100. For the next call you will skip 100 and take 100. This will give you records 101 to 200. On your third call you will skip 200 and take 100. This will give you records 201 to 250. In this manner, you can retrieve very large data sets for reporting or similar purposes while not impacting server performance by trying to download say 50,000 records at once.
If your usage may exceed the pagination cap, you need to set up a loop to make iterative calls and
get all results. Alternately, you could add a button for "Show next 100", display a warning that
the results are incomplete and more parameters should be provided or some other solution that makes
sense for your interface)
To assist with this process, each Paginated endpoint returns a body header with the link to grab the next batch of records which you can use to easily power your loop.
Auditing
All endpoints support the From parameter. The value you provide here is recorded in the audit log
along with your user, the call you are making and other metadata. If you are using a system user /
server / service account to power your interface, you may wish to log the user you are making the
request on behalf of via the From Parameter.
Agency administrators can review API authentications via the User Login Activity Module. They can audit access to records via the audit trail on the record itself or review histories in bulk from the Audit Trail Module.
Permissions
Permissions are an integral part of the API security structure. Each endpoint grouping has its own
permission that allows a user to engage with those endpoints. Endpoints are grouped into
<Permission Name> - Open and <Permission Name> - Edit groupings mirroring the access levels from
ProSuite. Open permissions grant access to GET and POST /search endpoints. Edit permissions
grant access to POST and PUT endpoints.
In addition to requiring permission to engage with the endpoint, certain endpoints also require
permissions to access the underlying records. Secondary permissions are required for endpoints that
host data of varying sensitivity For example with the case endpoint, just because you can interact
with cases doesn't mean you can interact with ALL cases; maybe your interface is only for "Patrol"
cases but not "Investigations" cases. Likewise, for Master Record Notes, maybe you have access to
"Officer Safety" Notes, but not "Confidential Informant" Notes.
Endpoints that require a secondary permission check will list the necessary permissions in the endpoint description.
Note that Sealed Records and Use for Intelligence Case Report or Record Note Types are NEVER
available in the API. Due to the extreme sensitivity of these items, they are not eligible for
interface transfer and any data transfer must occur through an agency-defined secure process such as
placing the Case Report on an encrypted thumb drive, hand delivering it to the prosecutor and
storing it in a safe while not in active use.