The Coly ME API Documentation provides descriptive information for developers who would like to integrate the functionality of the Coly ME API into their solution.
The Coly ME engine is provided in four simple steps.
The API endpoints are documented in the same order as the user flow above.
Go to API section to get started!
Our data models have several types(or layers) that define our approach. Simply speaking, the data lifecycle reveals steps and actions that should be taken to reach them.
Diagram1: Visualisation of model dependencies
Core-level models contain crucial data for system operations.
Created
- Creating an empty person record.Updated
- Update client's payload data.Joined2Group
- Creates new Assignment
records thus linking Person
and Group
.LeftGroup
- Set's Assignment
record as inactiveArchived
- Changes record access rights, thus making it read-only
. No updates or any other actions than recovery are available. At the end of the predefined archive record lifetime, it moves to the state Disabled
Disabled
- Restricts any further public access to data. Life-time defined by coly data retention policy.Anonymised
- Record is being stripped from personal or any sensitive information. Further access is intended solely for the ML training unit.
Created
- Creating empty group record.Updated
- Update client's payload data.PersonJoined
- Creates new Assignment
record thus linking Person
and Group
.PersonLeft
- Set's Assignment
record as inactive.Archived
- Changes record access rights, thus making it read-only
. No updates or any other actions than recovery are available. At the end of the predefined archive record lifetime, it moves to the state Disabled
.Disabled
- Restricts any further public access to data. Life-time defined by coly data retention policy.Anonymised
- Record is being stripped from personal or any sensitive information. Further access is intended solely for the ML training unit.
Base API URL:
xxxxxxxxxx
https://me-api.coly.io
To connect with our API, you will need to generate an API key. Please follow these steps:
After obtaining the API key, include it in all requests by setting the Authorization header as follows:
xxxxxxxxxx
Authorization: Application {yourApiKey}
Remember to replace {yourApiKey}
with your actual API key.
For example:
xxxxxxxxxx
Authorization: Application TfdZmYRpqVbqaHQoMMWKokbGLQPSvYzgjOhHwtRZJWZTeAObAaDbYzVKpnsjiqmf
Our API leverages the Either pattern, a common approach in functional programming, to standardize the structure of all responses. This strategy enables the API to always return a 200 status code, regardless of whether the operation was successful. The outcome of the operation is conveyed in the response's type field, which can be either 'success' or 'failure'.
Note: While the following example uses TypeScript, the 'Either' pattern is language-agnostic and can be adapted to your preferred programming language:
x
interface Success<T> {
type: 'success';
value: T;
}
interface Failure<E> {
type: 'failure';
value: E;
}
type Either<E, T> = Failure<E> | Success<T>;
In every response, you'll find the data property structured as one of the following:
xxxxxxxxxx
// Successful response:
{
"type": "success",
"value": { } // The requested data
}
// Failed response:
{
"type": "failure",
"value": { } // Error data
}
The value of a successfull response will vary across different requests, but all error messages will conform to this structure:
xxxxxxxxxx
interface Error {
code: FailCode;
message: string;
}
In this format, the message field provides a human-readable explanation primarily for debugging. However, it may change over time, so it should not be relied upon for application logic. On the other hand, the FailCode
is a unique, constant identifier for a specific type of failure and can be used to handle errors in your application.
Every API endpoint will provide a list of possible FailCodes for each request.
Here are examples of a successful and a failed request:
xxxxxxxxxx
// Successful request
GET http://localhost:7001/persons?search=adam
xxxxxxxxxx
// Successful response
{
"type": "success",
"value": {
"total": 1,
"list": [ { } ] // List of data
}
}
xxxxxxxxxx
// Failed request
GET http://localhost:7001/persons/abdca582-43d1-4dd8-f652-ad63451a75ad
xxxxxxxxxx
// Failed response
{
"type": "failure",
"value": {
"code": "Person::NotFound",
"message": "Specified person record wasn't found."
}
}
One common FailCode for all requests is InputValidation::Failed
, which signifies an issue with the request body format. Example:
xxxxxxxxxx
{
"type": "failure",
"value": {
"code": "InputValidation::Failed",
"message": "[Description of the validation fail]"
}
}
For the remainder of this API documentation, we will describe the structure of the 'value' field and the potential FailCodes for each request.
Although almost all requests return a 200 status code, there are a few exceptions:
404
: The requested route doesn't exist.401
: The provided API key is invalid.500
: A system error occurred on our side. This is unintentional and will be addressed promptly. If this happens please get in touch with the team at Coly.
For any of the entities below (person
and group
), the following query params are supported when fetching from the backend:
pageSize
: The number of records to return per page. This is used for pagination purposes.pageNumber
: The page number to return. This is used in conjunction with pageSize
for pagination.sortDirection
: The sorting direction, either asc
for ascending or desc
for descending.
Example:
xxxxxxxxxx
GET /persons?pageSize=20&pageNumber=1&sortDirection=asc
The Persons
entity mainly refers to the tenants within a shared living space, or persons taking the Psychometry Assessment
using our product. Each person will have their Personality
and coreValues
traits calculated after taking the assessment. The score they get will play a key role in matching the individual to a specific group.
Creates Persons
record and returns it. It requires email
, firstname
, lastname
to create a Persons
record.
xxxxxxxxxx
POST /persons
xxxxxxxxxx
{
"email": "james.bond@mymail.com",
"lastname": "Bond",
"firstname": "James"
}
xxxxxxxxxx
{
"id": "993abaa6-693b-456d-b58b-424057c5f0e3",
"createdAt": "2022-11-20T17:55:41.266Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-11-20T17:55:41.266Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": null,
"archivedBy": null,
"firstname": "James",
"lastname": "Bond",
"email": "james.bond@mymail.com",
"gender": null,
"language": null,
"country": null,
"birthDate": null,
"psychometry": null
}
Retrieve a single person's record with all the detailed pieces of information that you need.
xxxxxxxxxx
GET /persons/:id
xxxxxxxxxx
{
"id": "11131f6e-5654-4d72-bff0-b4d60b1c9b3a",
"createdAt": "2022-10-19T19:37:03.602Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-10-19T19:37:03.602Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": null,
"archivedBy": null,
"firstname": "Lucy",
"lastname": "Carlson",
"email": "lucy.carlson@mymail.com",
"gender": null,
"language": null,
"country": null,
"birthDate": null,
"psychometry": {
"traits": {
"personality": {
"emotionalStability": 100,
"conscientiousness": 100,
"agreeableness": 100,
"extroversion": 100,
"openness": 100
},
"coreValues": {
"selfDirection": 68.1000781861,
"universalism": 25.6450351837,
"achievement": 90.2267396403,
"benevolence": 38.7802971071,
"conformity": 67.4745895231,
"tradition": 88.8975762314,
"security": 88.4284597342,
"hedonism": 64.7380766224,
"activity": 63.6434714621,
"power": 93.6669272869
}
},
"submittedAt": "2022-10-19T19:47:03.891Z",
"requestedAt": "2022-10-19T19:37:03.891Z"
}
}
Retrieves the Persons
unique URL link for their Psychometry Assessment
and/or Coly ME profile
. This URL link will take you to the Coly ME Profile
App (https://profile.coly.io/). By default, when the Persons
opens the link, the Psychometry Assessment
will be presented. When Psychometry Assessment
is Ready
(completed), the link will display the Persons
Coly ME profile
with the result from the assessment.
xxxxxxxxxx
GET /persons/:id/link
xxxxxxxxxx
{
"link": "{{Base_url}}/auth/163326933613260363464326d203666626d223734643d243536353d25663661333131313"
}
Retrieves the list of person's records, with the total number of Persons
and their detailed pieces of information.
xxxxxxxxxx
GET /persons
xxxxxxxxxx
{
"total": 1,
"list": [
{
"id": "11131f6e-5654-4d72-bff0-b4d60b1c9b3a",
"createdAt": "2022-10-19T19:37:03.602Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-10-19T19:37:03.602Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": null,
"archivedBy": null,
"firstname": "Test",
"lastname": "erfan",
"email": "erfan@coly.io",
"gender": null,
"language": null,
"country": null,
"birthDate": null,
"psychometry": {
"traits": {
"personality": {
"emotionalStability": 100,
"conscientiousness": 100,
"agreeableness": 100,
"extroversion": 100,
"openness": 100
},
"coreValues": {
"selfDirection": 68.1000781861,
"universalism": 25.6450351837,
"achievement": 90.2267396403,
"benevolence": 38.7802971071,
"conformity": 67.4745895231,
"tradition": 88.8975762314,
"security": 88.4284597342,
"hedonism": 64.7380766224,
"activity": 63.6434714621,
"power": 93.6669272869
}
},
"submittedAt": "2022-10-19T19:47:03.891Z",
"requestedAt": "2022-10-19T19:37:03.891Z"
}
}
],
"isDone": false
}
include groups in persons with the following query param
xxxxxxxxxx
GET /persons?relations[]=group
Persons
record fields and returns updated person record.Psychometric Assessment
exists.xxxxxxxxxx
PUT /persons/:id
xxxxxxxxxx
{
"email": "james.dean@mymail.com",
"lastname": "Dean",
"firstname": "James"
}
xxxxxxxxxx
{
"id": "993abaa6-693b-456d-b58b-424057c5f0e3",
"createdAt": "2022-11-20T17:55:41.266Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-11-20T17:55:41.266Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": null,
"archivedBy": null,
"firstname": "James",
"lastname": "Dean",
"email": "james.dean@mymail.com",
"gender": null,
"language": null,
"country": null,
"birthDate": null,
"psychometry": null
}
Creates Psychometric Assessment
if none exists, and sends email request. If a psychometric assessment already exists a reminder email will be sent.
x
GET /persons/:id/invite
Archive Persons
record status.
xxxxxxxxxx
PATCH /persons/:id/archive
xxxxxxxxxx
{
"id": "993abaa6-693b-456d-b58b-424057c5f0e3",
"createdAt": "2022-11-20T17:55:41.266Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-11-20T17:55:41.266Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": "2022-11-20T18:10:01.449Z",
"archivedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"firstname": "James",
"lastname": "Dean",
"email": "james.dean@mymail.com",
"gender": null,
"language": null,
"country": null,
"birthDate": null,
"psychometry": {
"traits": {
"personality": {
"emotionalStability": 10.7896794371,
"conscientiousness": 2.7365129007,
"agreeableness": 0.5473025801,
"extroversion": 11.6497263487,
"openness": 9.3041438624
},
"coreValues": {
"selfDirection": 11.493354183,
"universalism": 0.7036747459,
"achievement": 41.2822517592,
"benevolence": 1.0946051603,
"conformity": 2.1892103206,
"tradition": 47.3025801407,
"security": 10.6333072713,
"hedonism": 1.8764659891,
"activity": 1.4073494918,
"power": 7.662236122
}
},
"submittedAt": "2023-05-19T11:34:04.535Z",
"requestedAt": "2023-05-19T11:34:02.396Z"
}
}
Restores a Persons
record from the archive.
xxxxxxxxxx
PATCH /persons/:id/restore
xxxxxxxxxx
{
"id": "993abaa6-693b-456d-b58b-424057c5f0e3",
"createdAt": "2022-11-20T17:55:41.266Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-11-20T17:55:41.266Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": null,
"archivedBy": null,
"firstname": "James",
"lastname": "Dean",
"email": "james.dean@mymail.com",
"gender": null,
"language": null,
"country": null,
"birthDate": null,
"psychometry": null
}
Disabling and deleting Persons
record from archived.
xxxxxxxxxx
DELETE /persons/:id
Note that only the archived records can be deleted.
When the desired record is missing:
xxxxxxxxxx
Person::NotFound
When creating a Person
record, the user's email should be unique and not be reused unless the person has been removed from the platform:
xxxxxxxxxx
Person::EmailUsed
For archived records, they are not allowed to be matched, or assigned to groups. To achieve this, you would need to restore the record first:
xxxxxxxxxx
Person::ArchiveStatusRestriction
For non-archived records, you would have to archive the record first to disable/delete it:
xxxxxxxxxx
Person::ArchiveStatusRequired
If there is a case of an unknown Error
, there is a high chance of server-side error. Contact us through our email dev@coly.io with detailed information about the error:
xxxxxxxxxx
Person::Unknown
The Groups
entity is a collection of Persons
. Usually refers to a group of Persons
who live in a shared living space. A group is created by title
and capacity
. A group with persons contains a calculated average score of the personality
and coreValues
, scale that can be used to match an incoming person.
Creates Group
record and returns it. It requires a Group name
and a capacity
of persons for the group.
xxxxxxxxxx
POST /groups
xxxxxxxxxx
{
"title": "Apartment A",
"capacity": 4,
}
xxxxxxxxxx
{
"id": "8291747b-f415-4854-95ff-40c43919201c",
"createdAt": "2022-11-17T21:13:37.601Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-11-17T21:13:37.601Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": null,
"archivedBy": null,
"title": "Apartment A",
"capacity": 4,
"psychometry": null
}
Retrieve a single Group
record with all the detailed pieces of information that you need, including Personality
and coreValues
percentile.
xxxxxxxxxx
GET /groups/:id
xxxxxxxxxx
{
"id": "c35321c0-a788-46f4-8e8a-b11007915275",
"createdAt": "2023-05-29T16:32:59.828Z",
"createdBy": "f892369b-1cab-4d8c-b24f-4603010975b9",
"updatedAt": "2023-05-29T16:32:59.828Z",
"updatedBy": "f892369b-1cab-4d8c-b24f-4603010975b9",
"archivedAt": null,
"archivedBy": null,
"title": "Highfield Avenue",
"capacity": 6,
"members": 4,
"status": "Vacant",
"psychometry": {
"updatedAt": "2023-05-30T16:31:34.350Z",
"traits": {
"personality": {
"emotionalStability": 18.7255668491,
"conscientiousness": 8.3072713057,
"agreeableness": 4.339327599675,
"extroversion": 7.46677091475,
"openness": 7.54495699765
},
"coreValues": {
"selfDirection": 13.623924941350001,
"universalism": 3.479280688,
"achievement": 5.531665363575,
"benevolence": 5.668491008599999,
"conformity": 15.519937451099999,
"tradition": 29.6520719312,
"security": 6.2744331509,
"hedonism": 18.706020328374997,
"activity": 16.849100860075,
"power": 17.386630179824998
}
}
}
}
Response Example 2:
xxxxxxxxxx
GET /groups/c35321c0-a788-46f4-8e8a-b11007915275?relations[]=persons
xxxxxxxxxx
{
"id": "c35321c0-a788-46f4-8e8a-b11007915275",
"createdAt": "2023-05-29T16:32:59.828Z",
"createdBy": "f892369b-1cab-4d8c-b24f-4603010975b9",
"updatedAt": "2023-05-29T16:32:59.828Z",
"updatedBy": "f892369b-1cab-4d8c-b24f-4603010975b9",
"archivedAt": null,
"archivedBy": null,
"title": "Highfield Avenue",
"image": null,
"capacity": 6,
"members": 2,
"status": "Vacant",
"psychometry": {
"updatedAt": "2023-05-30T18:51:43.460Z",
"traits": {
"personality": {
"emotionalStability": 18.7255668491,
"conscientiousness": 8.3072713057,
"agreeableness": 4.339327599675,
"extroversion": 7.46677091475,
"openness": 7.54495699765
},
"coreValues": {
"selfDirection": 13.623924941350001,
"universalism": 3.479280688,
"achievement": 5.531665363575,
"benevolence": 5.668491008599999,
"conformity": 15.519937451099999,
"tradition": 29.6520719312,
"security": 6.2744331509,
"hedonism": 18.706020328374997,
"activity": 16.849100860075,
"power": 17.386630179824998
}
}
},
"persons": [
{
"assignedAt": "2023-05-29T16:33:01.043Z",
"assignedBy": "f892369b-1cab-4d8c-b24f-4603010975b9",
"id": "f50df97f-3a47-4ee4-b2d1-05e4f52153d1",
"createdAt": "2023-05-29T16:32:59.676Z"
// ... etc
},
{
"assignedAt": "2023-05-29T16:33:01.062Z",
"assignedBy": "f892369b-1cab-4d8c-b24f-4603010975b9",
"id": "d20669bf-d132-4afc-a21b-6d1be0d9a0f8",
"createdAt": "2023-05-29T16:32:59.689Z"
// ... etc
}
]
}
Retrieves a list of Groups
records, with the total number of groups and detailed information about each group.
xxxxxxxxxx
GET /groups
xxxxxxxxxx
{
"total": 1,
"list": [
{
"id": "3747a4ab-a385-4215-9084-5c1479019ba6",
"createdAt": "2022-10-31T15:24:51.730Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-11-01T16:01:03.485Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": null,
"archivedBy": null,
"title": "Apartment A",
"capacity": 4,
"psychometry": {
"updatedAt": "2022-11-01T09:57:01.269Z",
"traits": {
"personality": {
"emotionalStability": 0,
"conscientiousness": 27.16966379985,
"agreeableness": 2.6192337764,
"extroversion": 85.3010164191,
"openness": 30.6880375293
},
"coreValues": {
"selfDirection": 14.425332290850001,
"universalism": 15.324472243899999,
"achievement": 75.29319781075,
"benevolence": 20.60203283815,
"conformity": 36.2392494136,
"tradition": 46.1884284597,
"security": 45.19155590305,
"hedonism": 44.05785770135,
"activity": 63.6434714621,
"power": 93.6669272869
}
}
}
}
],
"isDone": true
}
Groups that are empty.
xxxxxxxxxx
GET /groups?status=empty
Groups that are not empty:
xxxxxxxxxx
GET /groups?status=!empty
Groups with all stats and those who has vacancies:
xxxxxxxxxx
GET /groups?status[]=full&status[]=vacant
Groups with all stats but excluding vacant
:
xxxxxxxxxx
GET /groups?status[]=full&status[]=!vacant
NOTE: By design in query options exclusive "!*"
flags are prioritized, for example:
in the case above we first select all statuses except vacant
because the order doesn’t matter. And then we go along inclusive
or normal flags to include desired. So that the result of the last query is the following: “groups with all statuses excluding vacant
but including full
”. You can also exclude several. Duplications would be ignored.
include persons in groups with the following query param
xxxxxxxxxx
GET /groups?relations[]=persons
Updates Group
record fields and returns it updated. You can alter the name
and the capacity
of the group record you created.
xxxxxxxxxx
PUT /groups/:id
xxxxxxxxxx
{
"title": "Apartment A1",
"capacity": 2,
}
xxxxxxxxxx
{
"id": "8291747b-f415-4854-95ff-40c43919201c",
"createdAt": "2022-11-17T21:13:37.601Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-11-17T21:13:37.601Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": null,
"archivedBy": null,
"title": "Apartment A1",
"capacity": 2,
"psychometry": null
}
Archive Group
record status.
xxxxxxxxxx
PATCH /groups/:id/archive
xxxxxxxxxx
{
"id": "8291747b-f415-4854-95ff-40c43919201c",
"createdAt": "2022-11-17T21:13:37.601Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-11-17T22:40:37.575Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": "2022-11-17T22:42:26.613Z",
"archivedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"title": "Apartment A1",
"capacity": 2,
"psychometry": null
}
Restores a Group
record from the archive.
xxxxxxxxxx
PATCH /groups/:id/restore
xxxxxxxxxx
{
"id": "8291747b-f415-4854-95ff-40c43919201c",
"createdAt": "2022-11-17T21:13:37.601Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"updatedAt": "2022-11-17T22:40:37.575Z",
"updatedBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"archivedAt": null,
"archivedBy": null,
"title": "Apartment A1",
"capacity": 2,
"psychometry": null
}
Disabling and deleting Group
record from archived.
xxxxxxxxxx
DELETE /groups/:id
Note that only the archived records can be deleted.
xxxxxxxxxx
Status: 204 No content
When the desired record is missing:
xxxxxxxxxx
Group::NotFound
When creating a Group
record, the group's name should be unique. This includes the archived groups as well:
xxxxxxxxxx
Group::TitleUsed
For archived records, you'll need restore them before they can be used again:
xxxxxxxxxx
Group::ArchiveStatusRestriction
For non-archived records, you would have to archive the record first to disable/delete it:
xxxxxxxxxx
Group:ArchiveStatusRequired
In case there's an operation such as archive on a non-empty group record:
xxxxxxxxxx
Group::NotEmpty
If there is a case of an unknown Error, there is a high chance of server-side error. Contact us through email at dev@coly.io with detailed information about the error:
xxxxxxxxxx
Group::Unknown
Assignments
are used for adding and removing Persons
to and from a Group
. Assignments are indicating the relation between Persons
and Groups
records.
Assign a Person
to a Group
. You would need both groupId
and personId
to create assignment records.
xxxxxxxxxx
POST /assignments
xxxxxxxxxx
{
"groupId": "3747a4ab-a385-4215-9084-5c1479019ba6",
"personId": "11131f6e-5654-4d72-bff0-b4d60b1c9b3a"
}
xxxxxxxxxx
{
"id": "e73c70d1-76a1-4038-b42e-10892b4f1857",
"createdAt": "2022-11-20T18:21:52.668Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"leftAt": null,
"groupId": "3747a4ab-a385-4215-9084-5c1479019ba6",
"personId": "11131f6e-5654-4d72-bff0-b4d60b1c9b3a"
}
#####
Remove a Person
from a Group
. This closes the assignment for specified person by deleting or removing the assignment record.
xxxxxxxxxx
DELETE /assignments
xxxxxxxxxx
{
"personId": "11131f6e-5654-4d72-bff0-b4d60b1c9b3a"
}
xxxxxxxxxx
{
"id": "e73c70d1-76a1-4038-b42e-10892b4f1857",
"createdAt": "2022-11-20T18:21:52.668Z",
"createdBy": "72d6943c-2b64-43bf-8c38-93c83dc4edab",
"leftAt": "2022-11-20T18:23:41.404Z",
"groupId": "3747a4ab-a385-4215-9084-5c1479019ba6",
"personId": "11131f6e-5654-4d72-bff0-b4d60b1c9b3a"
}
When no vacancies are left for the group
, attempting to assign new person
records will not be possible:
xxxxxxxxxx
Group::Overflow
Person records are only allowed to be assigned to one group at a time. In case of attempting to assign to multiple groups:
xxxxxxxxxx
Person::GroupRestriction
Other error codes
These errors can also occure when attempting to assign records. Note that these are described in the person and group routes above:
xxxxxxxxxx
Person::ArchiveStatusRestriction
xxxxxxxxxx
Person::NotFound
xxxxxxxxxx
Group::ArchiveStatusRestriction
xxxxxxxxxx
Group::NotFound
The Matching Engine provides a method for evaluating the compatibility between individuals and groups within our system. Compatibility is quantified using a score ranging from 0 to 100. Detailed below are two endpoints:
The Match
function compares a single source
to multiple targets
, and generates an array of scores to indicate the level of compatibility between each source and target. source
can be a single person, single group, or a an array of persons (what we usually refer to as "virtual group"). targets
can be an array with combinations of groups, persons, or also a virtual groups.
The response includes an object with a results
field, which contains an array representing the compatibility of each match. The scores are indexed in the same order as the targets array in the request.
Request fields:
source
: Represents the single matching source.targets
: Represents the array of matching targets.type
: Indicates the type of entity being matched, with person
for a Person
, group
for a Group
, and virtualGroup
for an object containing a list of persons.id
: Represents the ID of the entity.Response fields:
results
: Contains an array of matching results, provided in the same order as the request.
type
: Indicates whether the matching was successful or not, with possible values of resolved
and rejected
.
For type: resolved
:
score
: A decimal number between 0 and 100, indicating the compatibility of the matches.type
: Will have the value "resolved".For type: rejected
:
message
: Provides information about why the matching result could not be calculated.code
: Contains the rejection code specific to the reason for the matching rejection.type
: Will have the value "rejected".
xxxxxxxxxx
POST /match
xxxxxxxxxx
{
"source": {
"type": "person",
"id": "a601daf0-fe21-4b02-9659-21c426e9b7a4"
},
"targets": [
{
"type": "group",
"id": "3747a4ab-a385-4215-9084-5c1479019ba6"
},
{
"type": "group",
"id": "5295a4ab-b456-9385-1056-4a1857492cd7"
}
]
}
xxxxxxxxxx
{
"results": [
{
"score": 77.92,
"type": "resolved"
},
{
"score": 86.24,
"type": "resolved"
}
],
}
xxxxxxxxxx
{
"source": {
"type": "virtualGroup",
"list": [
{
"type": "person",
"id": "a601daf0-fe21-4b02-9659-21c426e9b7a4"
},
{
"type": "person",
"id": "1d27c0ab-9c7b-4738-a2fd-0ca013c4de10"
}
]
},
"targets": [
{
"type": "group",
"id": "3747a4ab-a385-4215-9084-5c1479019ba6"
},
{
"type": "group",
"id": "5295a4ab-b456-9385-1056-4a1857492cd7"
}
]
}
xxxxxxxxxx
{
"results": [
{
"score": 59.57382039583729,
"type": "resolved"
},
{
"score": 71.64483092758392,
"type": "resolved"
}
],
}
xxxxxxxxxx
{
"source": [
{
"type": "person",
"id": "a601daf0-fe21-4b02-9659-21c426e9b7a4"
},
{
"type": "person",
"id": "1d27c0ab-9c7b-4738-a2fd-0ca013c4de10"
}
],
"targets": [
{
"type": "group",
"id": "3747a4ab-a385-4215-9084-5c1479019ba6"
},
{
"type": "person",
"id": "5295a4ab-b456-9385-1056-4a1857492cd7"
},
{
"type": "virtualGroup",
"list": [
{
"type": "person",
"id": "4df377f2-d6b0-4540-95f7-3fbc949d0015"
},
{
"type": "person",
"id": "6213111e-741b-43b1-a178-13ab09f62c30"
}
]
}
]
}
xxxxxxxxxx
{
"results": [
{
"score": 59.57382039583729,
"type": "resolved"
},
{
"score": 71.64483092758392,
"type": "resolved"
},
{
"score": 83.83191093758392,
"type": "resolved"
}
]
}
Example request 4: The second unit happens to be empty
xxxxxxxxxx
{
"source": {
"type": "person",
"id": "b601daf0-fe21-4b02-9659-21c426e9b7c7"
},
"targets": [
{
"type": "group",
"id": "1377a4ab-a385-4215-9084-5c1479019ba6"
},
{
"type": "group",
"id": "7201a4ab-b456-9385-1056-4a1857492vg7"
}
]
}
Example response 4: The response in case of a rejection
xxxxxxxxxx
{
"results": [
{
"score": 82.92,
"type": "resolved"
},
{
"type": "rejected",
"message": "There should be no empty source/target. Repeating persons are ignored.",
"code": "EmptyUnit"
}
]
}
The best match endpoint enables you to locate the best matching entity across the entire workspace for a specified source.
Request fields:
source
: Specifies the single source for matching.
type
: Type of entity being matched, person
for a Person
, group
for a Group
, and virtualGroup
for an object containing a list of persons (This source
field is identical to the one in the /match
endpoint)id
: Represents the ID of the entity.targetType
: This field specifies the type of entity you want to be included in your best match results. It can be either person
or group
.
Response fields:
results
: This field contains an array of match results, presented in descending order from the best match first.type
: Indicates the entity type, group
or person
. entity
: This field pertains to the entity of the matched item, which can be either a group or a person, as dictated by the type. For the schema of Group and Person entities, refer to the preceding sections.score
: The match score.As you may have noted, there are no differences between resolved
or rejected
requests - best match will exclusively contain resolved matches. At most, 20 items will be included, but this may be fewer if the system currently lacks a sufficient number of individuals or groups available for matching.
xxxxxxxxxx
POST /match/best
xxxxxxxxxx
{
"source": { "type": "person", "id": "d805cf84-1237-4ffd-bbda-f5d66b09ce72" },
"targetType": "group"
}
xxxxxxxxxx
{
"results": [
{
"type": "group",
"entity": {
"id": "ce602e65-1c11-4b53-9d68-d4911c5ec4eb",
"createdAt": "2023-05-19T11:33:58.759Z",
"createdBy": "f892369b-1cab-4d8c-b24f-4603010975b9",
"title": "Apple Acre",
"status": "Vacant",
// ... etc
},
"score": 95.02
},
{
"type": "group",
"entity": {
"id": "02982527-c090-4024-af39-a565b641c466",
"createdAt": "2023-05-19T11:33:58.827Z",
"createdBy": "f892369b-1cab-4d8c-b24f-4603010975b9",
// ... etc
},
"score": 94.63
},
// ... etc
]
}
Overlap handling is implemented for all matching requests. It takes into account situations where some individuals appearing in the source also exist in the target entities. This may happen, for example, when matching an individual with a group in which they are already a member. The default procedure for managing such scenarios involves the following steps:
By applying these rules, the overlap handling ensures that the same person doesn't feature in both the source and target when a match is being calculated, thus maintaining the integrity of the matching process.
xxxxxxxxxx
Person::NotFound
xxxxxxxxxx
Group::NotFound
These are described in the person and group routes.
In the context of the API, there's a throttler mechanism that enforces rate limits on the number of requests a client can make to ensure that the API remains responsive and available for all clients and to prevent one client from monopolizing the resources of the API.
When a client exceeds the rate limit, the API will return a 429 error to indicate that the client has exceeded its allowed number of requests. The client should wait a certain amount of time before retrying the request. The duration of the waiting time is included in the response headers in the form of the 'Retry-After' header.
xxxxxxxxxx
A 429 error, also known as a "Too Many Requests" error, is an HTTP status code that indicates that the user has sent too many requests in a given amount of time. This type of error is typically used to prevent a client from overwhelming a server with too many requests in a short period of time.
Please note that any data found on an object that is not explicitly mentioned in this document is not officially supported. Such values are susceptible to alterations at any time without prior notice.