Understanding rulesets
How to use rulesets with the Oyster API
Some of our endpoints - particular those for creating resources - have more complicated schemas, rules and source data; and some of those rules are dependent on external factors such as:
- The team member's home country
- The currency
Representing these rules in static documentation would be impractical, so instead this information is available via rulesets.
What is a ruleset?
A ruleset is a JSON document that describes the schema and rules for a particular endpoint. Some endpoints have multiple rulesets - which depend on external factors such as country code - and some endpoints have a single default ruleset that applies to all cases.
Structure of a ruleset
A ruleset follows the following JSON Schema format:
{
"type": "object",
"properties": {
"rulesetId": {
"type": "string",
"title": "The unique ID of this ruleset",
"description": "The ruleset ID is unique within the domain"
},
"domain": {
"type": "string"
},
"scope": {
"type": "object",
"title": "The scope (e.g. country) for which this ruleset applies",
"description": "For default rulesets, the scope will be empty",
"additionalProperties": {
"type": "string"
}
},
"context": {
"type": "object",
"title": "Useful information related to the scope of the ruleset",
"additionalProperties": {
"type": "string"
}
},
"schemas": {
"type": "object",
"properties": {
"post": {
"oneOf": [
{
"type": "object",
"title": "Schema for body structure of POST requests",
"description": "Must be a schema conforming to JSON Schema"
},
{
"enum": ["patch", "put"],
"title": "Reuse the schema defined for PATCH or PUT requests"
}
]
},
"patch": {
"oneOf": [
{
"type": "object",
"title": "Schema for body structure of PATCH requests",
"description": "Must be a schema conforming to JSON Schema"
},
{
"enum": ["post", "put"],
"title": "Reuse the schema defined for POST or PUT requests"
}
]
},
"put": {
"oneOf": [
{
"type": "object",
"title": "Schema for body structure of PUT requests",
"description": "Must be a schema conforming to JSON Schema"
},
{
"enum": ["post", "patch"],
"title": "Reuse the schema defined for POST or PATCH requests"
}
]
}
}
},
"sources": {
"type": "object",
"title": "Provides information about how to fetch source data",
"description": "Source data are things like lists of values for dropdown selections"
}
},
"required": ["rulesetId", "domain", "scope", "schemas"]
}
rulesetId
rulesetId
The unique ID of this ruleset within its domain. Default rulesets will have a ruleset ID of DEFAULT
. The rulesetId
can be used to fetch a specific ruleset; e.g.:
/{version}/expenses/rulesets/default
/{version}/bank_accounts/rulesets/KES-KE-LOCAL
domain
domain
If the ruleset does not specify a domain
, then the domain can be assumed to be the part of the path preceding /rulesets
; i.e.:
The domain of a ruleset returned from /{version}/expenses/rulesets
is expenses
.
scope
scope
Dynamic rulesets are those that are dependent on external factors such as country. Those external factors define the scope of the ruleset. For example, the ruleset for hiring team members in the United States would be fetched using:
/{version}/hiring/rulesets?country_code=US
In this case, the scope of the returned ruleset would be:
{
"scope": {
"countryCode": "US"
}
}
context
context
When fetching a ruleset, there might be additional useful information provided. For example, in the payroll_changes
domain, you need to provide an engagement ID scope to fetch the correct ruleset for a given engagement:
/{version}/payroll_changes/rulesets?engagement_id=ABCD1234
This will return a ruleset with the following scope:
{
"scope": {
"engagementId": "ABCD1234"
}
}
As part of your use case, you may also need to know the next cut-off date of that engagement's payroll, and also the engagement's salary currency. These will be provided by the context
property; e.g.:
{
"context": {
"currencyCode": "USD",
"cutoffDate": "2024-09-10"
}
}
The context is not part of the ruleset itself, but is instead relevant to the scope of the ruleset and the time it was requested.
schemas
schemas
For most POST
endpoints, you will be required to include a payload of data. That data must be formatted correctly according to the defined schema for that endpoint, otherwise you may receive a 400 - Bad Request
response from the endpoint. Endpoints with dynamic rulesets may also have dynamic schemas; and so the schema for a specific ruleset is provided in the schemas
property. Schemas are JSON Schema documents.
sources
sources
You may be required to provide values to POST
endpoints that come from predefined lists. Sometimes these values are provided as enum
fields in the schema. However, enums are not always the right mechanism to provide lists of data; in particular the do not support descriptions or other meta information. This is where sources come in.
The sources
section of the schema will provide you with the means to fetch source data for the given ruleset. For example, when posting a new expense to the /expenses
domain, you need will to include a value for the category
property, and the value must come from a list of supported expense categories.
In the expense ruleset you will see the categories
source:
{
"sources": {
"categories": {
"params": {}
}
}
This means you can fetch the expenses categories from the following endpoint:
/{version}/expenses/rulesets/{rulesetId}/categories
params
params
Some sources endpoints may require additional parameters, and these are described by the params
property. If params
is empty, then you can call the source endpoint with no additional parameters.
Default rulesets
Some endpoints have a single default ruleset that applies to all cases. Default rulesets have a rulesetId
of DEFAULT
.
If a /rulesets
endpoint returns a single ruleset with the ruleset ID DEFAULT
, then that is the only ruleset the endpoint requires.
The default ruleset can always be fetched using the /rulesets/default
endpoint; e.g.:
/{version}/expenses/rulesets/default
Endpoints that do not support a default ruleset will return 404 - Not Found
.
The default ruleset can also be fetched using the convenience /ruleset
endpoint; e.g.:
/{version}/expenses/ruleset
Endpoints that do not support a default ruleset will return 404 - Not Found
.
Default sources
For endpoints with a default ruleset and sources, additional convenience endpoints exist to support sources. For example, for expense categories:
/{version}/expenses/categories
...is the equivalent of:
/{version}/expenses/rulesets/default/categories
Endpoints that do not support a default ruleset will return 404 - Not Found
.
Updated about 2 months ago