API Philosophy

Welcome to the ConnectNow APIs docs!

General principles

You must pass an accept header with the value of application/json for all API requests: 'Accept' => 'application/json',.

Most endpoints use standard CRUD and REST API principles, using GET, POST, DELETE, and PUT for updates. All resources are plural; you'd use GET /api/users to list all users and GET /api/users/1 to list a single user.

Authentication

STOP

API tokens are secret, so do not share or publicly expose them. If you think one of your API tokens has been compromised, generate a new one.

Some endpoints require authentication. Endpoints that do require authentication will be marked as such in the docs.

Getting an API token

To get an API token, you should refer to the user guide of the service you want to authenticate with. Usually, ConnectNow applications will allow you to create personal API tokens on the websites of each service, after you have logged in.

Authenticating requests

TIP

If you are getting back a 401 error code, this means your token is not valid or the way you are passing it is incorrect. This is different to a 403, which is telling you that you are not allowed to do something (but your token may be valid).

Via query parameters

To authenticate, you can either pass a api_token as a query parameter: e.g. GET /api/users?api_token={token}.

Via the request payload

You can post the API token as part of the actual request payload, especially when making POST requests. The form parameter is api_token.

Via headers

You can provide the API token as a Bearer token in the Authorization header of the request: 'Authorization' => 'Bearer '.$token,.

Response status codes

ConnectNow APIs return the following status codes in its API:

Status CodeDescriptionMeaning
200OKAll good
201CREATEDThe resource has been successfully created
202ACCEPTEDThe request made has been accepted, and is scheduled for processing
401UNAUTHENTICATEDYour API token, or the way you are passing it, is incorrect
403FORBIDDENYou are not allowed to do the action
404NOT FOUNDThe resource you are looking for does not exist
405METHOD NOT ALLOWEDYou are not allowed to use a given HTTP method (GET, POST, PUT, DELETE, or others)
422BAD REQUESTYour request is malformed, data required is missing and/or incorrect
429TOO MANY REQUESTSYou have exceeded the rate-limiter limits
500INTERNAL SERVER ERRORThere was a problem with the server - if you encounter this one, please let us know

More general information about status codes can be found here: https://developer.mozilla.org/en-GB/docs/Web/HTTP/Status

Paginated responses

Some responses are paginated. You can access additional pages by passing the page parameter. Paginated responses include additional information to help you build pagination on the frontend.

By default, 15 results will be returned per page. You can choose to return up to 249 records per page or less by passing the per_page parameter.

{
	"current_page": 1,
	"data": [
		...
	],
	"first_page_url": "https://api.connectnow.org.uk/api/models?page=1",
	"from": 1,
	"next_page_url": "https://api.connectnow.org.uk/api/models?page=2",
	"path": "https://api.connectnow.org.uk/api/models",
	"per_page": 15,
	"prev_page_url": null,
	"to": 15
}

If there is no more next or previous pages, the values will be null.

Rate limiting

A rate limiter is implemented on all endpoints. Some can be as low as one request per minute, depending on the endpoint. If you exceed a given rate-limiter limit, you will get back a 429 status code. Wait a few minutes before trying again; note that some responses will tell you how much time you have to wait in the response headers.

Filtering

WARNING

This is still in active development, and not fully supported. For now we are rolling it out to the queue system.

Some endpoints using GET support filtering. We are always working on supporting more.

For endpoints that do support filtering and that return a list (e.g. /api/companies), you can try to pass additional filtering options.

Filtering by dates

ParameterTypeRulesDefaultDescription
beforedateA valid date-Filter by objects created before or on this date
afterdateA valid date-Filter by objects created on or after this date

Note that most types of dates will work, including 24-12-2021, or 24th December 2021.

However, dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed. If, however, the year is given in a two digit format and the separator is a dash (-), the date string is parsed as y-m-d.

To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) dates.

An invalid date passed to either parameter will yield a 422 error.

Filtering with scopes

ParameterTypeRulesDefaultDescription
scopesarrayAn array of valid scopes-Filter by objects created before or on this date

You can filter by valid model scopes to further limit the results you get back.

Additionally, all models implementing filtering with scopes also have a latest scope, which will order results returned from newest to oldest.

Expanding objects & appending data

WARNING

This is still in active development, and not fully supported. Currently some endpoints in the queue system and issue tracker support this.

Some endpoints using GET support expanding the returned objects. When they do, they will have an entry in their respective parameter tables for with.

For example, imagine that users belong to companies. To fetch companies with the users nested in the response, you can append the data when calling the API, like so: /api/companies?with[]=users.

You can also further expand expanded objects with dot notation. Assuming that in the above example users also have pets, we can retrieve a 3 nested response with /api/companies?with[]=users.pets. You can even go deep multiple levels: /api/companies?with[]=users.pets.favoriteToys.

You can expand multiple objects by including with again, like so: /api/companies?with[]=users&with[]=offices.

You can just get the count of a related model by calling withCount instead of with. Note that withCount does not support using dot notation for nested objects.

Note that expandable objects are validated when calling the API, so if you expand with an object that doesn't exist or isn't allowed, you will get a 422 error. Refer to the documentation of each service to see the objects you can expand.