Introduction
The MYBOS building-management API.
Every request is made on behalf of a principal -- a user, or a company's service account -- and nearly all data is limited to the buildings that principal can reach. See the Authentication section for how to get a token before calling anything else.
Conventions
Responses follow JSON:API shapes
(data/errors, type/id/attributes/relationships, meta,
links) and are served as plain application/json. The API is not a
fully compliant JSON:API server: it does not implement JSON:API content
negotiation.
- Identifiers are strings, opaque to callers. Use them as given; never construct one.
- Dates are ISO-8601 in UTC.
- Building scope. A collection that holds building data takes a
buildingsparameter: a comma-separated list of building identifiers fromGET /api/v1/buildings. Omit it to cover every building the credential can reach. Naming a building the credential cannot reach fails the whole request with403 building_not_accessible, rather than quietly leaving that building out. - Paging. Paged collections take
page[size](default 50, maximum 250) and returnlinks.next/links.prev. Follow those links as given: thepage[cursor]they carry is opaque, and only valid for the exact request that produced it.links.nextisnullon the last page.meta.totalcounts the whole result, across every page. - Errors are an
errorsarray; each entry hasstatus, a stable machine-readablecode, atitle, and usually adetailand asourcenaming the offending parameter. Branch oncode, never ondetail, whose wording may change. - Not found is not forbidden. A record that does not exist and one the
credential cannot reach both answer
404, so a response never reveals that a record exists.403means the record is reachable but the credential lacks the permission the operation needs.
Authenticating requests
To authenticate requests, include an Authorization header with the
value "Bearer {ACCESS_TOKEN}". Endpoints that don't require this are
marked unauthenticated.
How to get an access token
This API does not issue tokens. Access tokens are short-lived signed tokens issued by the MYBOS Auth service; this API only verifies them.
With a company service account (recommended for integrations)
A service account is a login for your company's own system -- a reporting job, a data sync -- rather than for a person. It keeps working when staff change.
1. Create the service account. In the MYBOS company portal, go to Settings › API / Service Accounts and choose New Service Account. You get a client ID and a client secret. The secret is shown once: store it like a password. It expires after one year; create a new one before then.
2. Exchange them for an access token at the Auth service's token endpoint, as a form post:
curl -s https://auth.mybos.com/oauth/token \
-H 'Accept: application/json' \
-d grant_type=client_credentials \
-d client_id='YOUR_CLIENT_ID' \
-d client_secret='YOUR_CLIENT_SECRET'
{
"token_type": "Bearer",
"expires_in": 900,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs..."
}
3. Call this API with the token in the Authorization header:
curl -s https://keystone.mybos.com/api/v1/cases \
-H 'Accept: application/json' \
-H 'Authorization: Bearer ACCESS_TOKEN'
4. Get a new token when it expires. Tokens last expires_in seconds
(15 minutes). There is no refresh token for service accounts: repeat step 2.
Keep the client ID and secret in your system, not the token.
A service-account token acts as the company: it can read data in the buildings the company owns, and cannot change anything.
If step 2 fails with 401 invalid_client, the client ID or secret is
wrong, the secret has expired, or the service account was revoked.
| Environment | Auth service (token endpoint) | This API |
|---|---|---|
| Production | https://auth.mybos.com/oauth/token |
https://keystone.mybos.com |
| Staging | https://auth.stg.mybos.com/oauth/token |
https://keystone.stg.mybos.com |
Other ways to get a token
- Acting for a user (an app a person signs in to): use the Auth
service's OAuth
authorization_codeflow. The token acts with that user's access. - Testing as yourself: create a personal access token in the Auth service. Treat it like a password -- it carries your full access until it expires or is revoked.
What a token can reach
A token's access is decided per request, from the principal it names: the buildings that principal can reach, and the permissions it holds in each (for example, reading cases). The same credential sees the same data whichever endpoint it calls.
An expired token is refused with 401 token_expired; any other invalid or
missing token with 401 invalid_token.
Credential
Who am I
requires authentication
Describes the principal this token acts for -- a user, or a company's service account -- and the session the token carries.
Example request:
curl --request GET \
--get "https://keystone.stg.mybos.com/api/v1/me" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Accept: application/json"const url = new URL(
"https://keystone.stg.mybos.com/api/v1/me"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, A user's token):
{
"data": {
"type": "users",
"id": "6650a0e9c4e8b90012ab3401",
"attributes": {
"firstName": "Alex",
"lastName": "Taylor",
"email": "alex.taylor@example.com",
"username": "alex.taylor",
"group": "BUILDING MANAGER",
"status": "Active"
}
},
"meta": {
"session": {
"subject": "9d1c6f0e-2b7a-4c1e-8f3a-5b6d7e8f9a01",
"audience": "00000000-0000-7000-9000-000000000001",
"ownerType": "user",
"ownerId": "9d1c6f0e-2b7a-4c1e-8f3a-5b6d7e8f9a01",
"scopes": [],
"expiresAt": "2026-10-27T10:00:00+00:00"
}
},
"links": {
"self": "/api/v1/me"
}
}
Example response (401, Missing, invalid or expired token):
{
"errors": [
{
"status": "401",
"code": "invalid_token",
"title": "Unauthenticated"
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Buildings
List buildings
requires authentication
The buildings this credential can reach, or the named ones. Their
identifiers are what every buildings parameter takes.
Example request:
curl --request GET \
--get "https://keystone.stg.mybos.com/api/v1/buildings?buildings=6650a1f2c4e8b90012ab34c1&page%5Bsize%5D=50&page%5Bcursor%5D=eyJmIjoiOGQ5ZiIsImQiOiJuZXh0IiwidiI6W3siJG9pZCI6IjY3MTJlOGIxZDFjM2U1MDAxYTJiM2MxMSJ9XX0" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Accept: application/json"const url = new URL(
"https://keystone.stg.mybos.com/api/v1/buildings"
);
const params = {
"buildings": "6650a1f2c4e8b90012ab34c1",
"page[size]": "50",
"page[cursor]": "eyJmIjoiOGQ5ZiIsImQiOiJuZXh0IiwidiI6W3siJG9pZCI6IjY3MTJlOGIxZDFjM2U1MDAxYTJiM2MxMSJ9XX0",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1",
"attributes": {
"name": "Harbour View",
"plan": "SP 12345",
"units": 120,
"timezone": "Australia/Sydney",
"status": "Active"
}
}
],
"meta": {
"total": 1,
"scope": {
"origin": "defaulted"
}
},
"links": {
"self": "/api/v1/buildings",
"first": "/api/v1/buildings",
"next": null,
"prev": null
}
}
Example response (400, A cursor from a different request):
{
"errors": [
{
"status": "400",
"code": "invalid_cursor",
"title": "Invalid cursor",
"detail": "The cursor does not belong to this query. Restart without page[cursor].",
"source": {
"parameter": "page[cursor]"
}
}
]
}
Example response (401, Missing, invalid or expired token):
{
"errors": [
{
"status": "401",
"code": "invalid_token",
"title": "Unauthenticated"
}
]
}
Example response (403, A named building is not accessible):
{
"errors": [
{
"status": "403",
"code": "building_not_accessible",
"title": "Forbidden",
"detail": "One or more requested buildings are not accessible with this credential.",
"meta": {
"buildings": [
"6650a1f2c4e8b90012ab34c2"
]
}
}
]
}
Example response (422, A malformed building identifier):
{
"errors": [
{
"status": "422",
"code": "validation_failed",
"title": "Unprocessable",
"detail": "Each building identifier is malformed.",
"source": {
"parameter": "buildings"
}
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Cases
Scribe documents the {case} placeholder as {id}, so the tag must be
named id to attach to it (see the openapi-scribe-docs skill).
List cases
requires authentication
Maintenance and work cases in the buildings where this credential may
read them, in every state, newest first. A building the credential can
reach but may not read cases in is left out, unless it was named in
buildings, which fails the request instead.
Filters and sorting are not offered yet: any filter[...] or sort
is refused rather than ignored.
Example request:
curl --request GET \
--get "https://keystone.stg.mybos.com/api/v1/cases?buildings=6650a1f2c4e8b90012ab34c1&page%5Bsize%5D=50&page%5Bcursor%5D=eyJmIjoiOGQ5ZiIsImQiOiJuZXh0IiwidiI6W3siJG9pZCI6IjY3MTJlOGIxZDFjM2U1MDAxYTJiM2MxMSJ9XX0" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Accept: application/json"const url = new URL(
"https://keystone.stg.mybos.com/api/v1/cases"
);
const params = {
"buildings": "6650a1f2c4e8b90012ab34c1",
"page[size]": "50",
"page[cursor]": "eyJmIjoiOGQ5ZiIsImQiOiJuZXh0IiwidiI6W3siJG9pZCI6IjY3MTJlOGIxZDFjM2U1MDAxYTJiM2MxMSJ9XX0",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"type": "cases",
"id": "6712f0a4d1c3e5001a2b3c4d",
"attributes": {
"number": 1042,
"subject": "Leak in level 3 corridor",
"detail": "<p>Water is leaking from the ceiling in the level 3 corridor.</p>",
"history_note": null,
"areas": [
"common_asset"
],
"state": "open",
"starred": true,
"starts_at": null,
"due_at": "2026-10-27T07:00:00+00:00",
"completed_at": null,
"purchase_order_number": null,
"work_order": "WO-1042",
"logged_by": "Concierge",
"created_at": "2026-10-20T03:15:00+00:00",
"updated_at": "2026-10-20T03:15:00+00:00"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
},
"status": {
"data": {
"type": "case-statuses",
"id": "6650a2a0c4e8b90012ab3502"
}
},
"type": {
"data": {
"type": "case-types",
"id": "6650a2b5c4e8b90012ab3601"
}
},
"priority": {
"data": {
"type": "case-priorities",
"id": "6650a2c9c4e8b90012ab3701"
}
}
}
},
{
"type": "cases",
"id": "6712e8b1d1c3e5001a2b3c11",
"attributes": {
"number": 1041,
"subject": "Replace foyer light",
"detail": "<p>The foyer downlight near the lifts has failed.</p>",
"history_note": null,
"areas": [
"common_non_asset"
],
"state": "completed",
"starred": false,
"starts_at": null,
"due_at": "2026-10-19T07:00:00+00:00",
"completed_at": "2026-10-19T05:30:00+00:00",
"purchase_order_number": null,
"work_order": "WO-1038",
"logged_by": "Concierge",
"created_at": "2026-10-18T22:40:00+00:00",
"updated_at": "2026-10-18T22:40:00+00:00"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
},
"status": {
"data": {
"type": "case-statuses",
"id": "6650a2a0c4e8b90012ab3504"
}
},
"type": {
"data": {
"type": "case-types",
"id": "6650a2b5c4e8b90012ab3602"
}
},
"priority": {
"data": {
"type": "case-priorities",
"id": "6650a2c9c4e8b90012ab3702"
}
}
}
}
],
"meta": {
"total": 62,
"scope": {
"origin": "defaulted"
}
},
"links": {
"self": "/api/v1/cases?page%5Bsize%5D=2",
"first": "/api/v1/cases?page%5Bsize%5D=2",
"next": "/api/v1/cases?page%5Bsize%5D=2&page%5Bcursor%5D=eyJmIjoiOGQ5ZiIsImQiOiJuZXh0IiwidiI6W3siJG9pZCI6IjY3MTJlOGIxZDFjM2U1MDAxYTJiM2MxMSJ9XX0",
"prev": null
}
}
Example response (400, A filter or sort was sent):
{
"errors": [
{
"status": "400",
"code": "invalid_filter",
"title": "Bad Request",
"detail": "This collection offers no filters.",
"source": {
"parameter": "filter[state]"
}
}
]
}
Example response (400, A cursor from a different request):
{
"errors": [
{
"status": "400",
"code": "invalid_cursor",
"title": "Invalid cursor",
"detail": "The cursor does not belong to this query. Restart without page[cursor].",
"source": {
"parameter": "page[cursor]"
}
}
]
}
Example response (401, Missing, invalid or expired token):
{
"errors": [
{
"status": "401",
"code": "invalid_token",
"title": "Unauthenticated"
}
]
}
Example response (403, A named building is not accessible):
{
"errors": [
{
"status": "403",
"code": "building_not_accessible",
"title": "Forbidden",
"detail": "One or more requested buildings are not accessible with this credential.",
"meta": {
"buildings": [
"6650a1f2c4e8b90012ab34c2"
]
}
}
]
}
Example response (403, Cases may not be read in a named building):
{
"errors": [
{
"status": "403",
"code": "forbidden",
"title": "Forbidden",
"detail": "This credential is not permitted to read cases in one or more of the requested buildings."
}
]
}
Example response (422, An invalid page size):
{
"errors": [
{
"status": "422",
"code": "validation_failed",
"title": "Unprocessable",
"detail": "The page[size] must be a whole number between 1 and 250.",
"source": {
"parameter": "page[size]"
}
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get a case
requires authentication
One case. A case that does not exist and one this credential cannot
reach are both 404, so the response never reveals that a case
exists.
Example request:
curl --request GET \
--get "https://keystone.stg.mybos.com/api/v1/cases/6712f0a4d1c3e5001a2b3c4d" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Accept: application/json"const url = new URL(
"https://keystone.stg.mybos.com/api/v1/cases/6712f0a4d1c3e5001a2b3c4d"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"type": "cases",
"id": "6712f0a4d1c3e5001a2b3c4d",
"attributes": {
"number": 1042,
"subject": "Leak in level 3 corridor",
"detail": "<p>Water is leaking from the ceiling in the level 3 corridor.</p>",
"history_note": null,
"areas": [
"common_asset"
],
"state": "open",
"starred": true,
"starts_at": null,
"due_at": "2026-10-27T07:00:00+00:00",
"completed_at": null,
"purchase_order_number": null,
"work_order": "WO-1042",
"logged_by": "Concierge",
"created_at": "2026-10-20T03:15:00+00:00",
"updated_at": "2026-10-20T03:15:00+00:00"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
},
"status": {
"data": {
"type": "case-statuses",
"id": "6650a2a0c4e8b90012ab3502"
}
},
"type": {
"data": {
"type": "case-types",
"id": "6650a2b5c4e8b90012ab3601"
}
},
"priority": {
"data": {
"type": "case-priorities",
"id": "6650a2c9c4e8b90012ab3701"
}
}
}
},
"meta": {},
"links": {
"self": "/api/v1/cases/6712f0a4d1c3e5001a2b3c4d"
}
}
Example response (401, Missing, invalid or expired token):
{
"errors": [
{
"status": "401",
"code": "invalid_token",
"title": "Unauthenticated"
}
]
}
Example response (403, The case is reachable, but cases may not be read in its building):
{
"errors": [
{
"status": "403",
"code": "forbidden",
"title": "Forbidden",
"detail": "This credential is not permitted to read this case."
}
]
}
Example response (404, No such case, or not reachable):
{
"errors": [
{
"status": "404",
"code": "not_found",
"title": "Not Found",
"detail": "No case with that id is accessible to this credential."
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List a case's activity
requires authentication
What has happened to one case, newest first: each entry says what
changed, who did it and when. by is null when the person no longer
exists. The order is fixed: any filter[...] or sort is refused
rather than ignored.
A case that does not exist and one this credential cannot reach are
both 404, so the response never reveals that a case exists.
Example request:
curl --request GET \
--get "https://keystone.stg.mybos.com/api/v1/cases/6712f0a4d1c3e5001a2b3c4d/activity?page%5Bsize%5D=50&page%5Bcursor%5D=eyJmIjoiOGQ5ZiIsImQiOiJuZXh0IiwidiI6WzE3MjkzOTQxMDAwMDAsM119" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Accept: application/json"const url = new URL(
"https://keystone.stg.mybos.com/api/v1/cases/6712f0a4d1c3e5001a2b3c4d/activity"
);
const params = {
"page[size]": "50",
"page[cursor]": "eyJmIjoiOGQ5ZiIsImQiOiJuZXh0IiwidiI6WzE3MjkzOTQxMDAwMDAsM119",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"type": "case-activities",
"id": "6714a1c2d1c3e5001a2b3d02",
"attributes": {
"description": "Status changed from New to In Progress",
"by": "Jordan Lee",
"created_at": "2026-10-21T01:40:00+00:00"
}
},
{
"type": "case-activities",
"id": "6712f0a4d1c3e5001a2b3d01",
"attributes": {
"description": "Case created",
"by": "Jordan Lee",
"created_at": "2026-10-20T03:15:00+00:00"
}
}
],
"meta": {
"total": 2
},
"links": {
"self": "/api/v1/cases/6712f0a4d1c3e5001a2b3c4d/activity",
"first": "/api/v1/cases/6712f0a4d1c3e5001a2b3c4d/activity",
"next": null,
"prev": null
}
}
Example response (400, A filter or sort was sent):
{
"errors": [
{
"status": "400",
"code": "invalid_filter",
"title": "Bad Request",
"detail": "This collection offers no filters.",
"source": {
"parameter": "filter[by]"
}
}
]
}
Example response (400, A cursor from a different request):
{
"errors": [
{
"status": "400",
"code": "invalid_cursor",
"title": "Invalid cursor",
"detail": "The cursor does not belong to this query. Restart without page[cursor].",
"source": {
"parameter": "page[cursor]"
}
}
]
}
Example response (401, Missing, invalid or expired token):
{
"errors": [
{
"status": "401",
"code": "invalid_token",
"title": "Unauthenticated"
}
]
}
Example response (403, The case is reachable, but cases may not be read in its building):
{
"errors": [
{
"status": "403",
"code": "forbidden",
"title": "Forbidden",
"detail": "This credential is not permitted to read this case."
}
]
}
Example response (404, No such case, or not reachable):
{
"errors": [
{
"status": "404",
"code": "not_found",
"title": "Not Found",
"detail": "No case with that id is accessible to this credential."
}
]
}
Example response (422, An invalid page size):
{
"errors": [
{
"status": "422",
"code": "validation_failed",
"title": "Unprocessable",
"detail": "The page[size] must be a whole number between 1 and 250.",
"source": {
"parameter": "page[size]"
}
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Case options
List case statuses
requires authentication
The case statuses of the buildings where this credential may read
cases, ordered by building, then each building's own display order. Each status also gives the state a case is in while it has that status: open, completed or trashed.
Every status is returned at once: this collection is not paginated.
Example request:
curl --request GET \
--get "https://keystone.stg.mybos.com/api/v1/case-statuses?buildings=6650a1f2c4e8b90012ab34c1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Accept: application/json"const url = new URL(
"https://keystone.stg.mybos.com/api/v1/case-statuses"
);
const params = {
"buildings": "6650a1f2c4e8b90012ab34c1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"type": "case-statuses",
"id": "6650a2a0c4e8b90012ab3501",
"attributes": {
"name": "New",
"state": "open"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
}
}
},
{
"type": "case-statuses",
"id": "6650a2a0c4e8b90012ab3502",
"attributes": {
"name": "In Progress",
"state": "open"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
}
}
},
{
"type": "case-statuses",
"id": "6650a2a0c4e8b90012ab3504",
"attributes": {
"name": "Completed",
"state": "completed"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
}
}
},
{
"type": "case-statuses",
"id": "6650a2a0c4e8b90012ab3505",
"attributes": {
"name": "Deleted",
"state": "trashed"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
}
}
}
],
"meta": {
"total": 4,
"scope": {
"origin": "defaulted"
}
},
"links": {
"self": "/api/v1/case-statuses",
"first": "/api/v1/case-statuses",
"next": null,
"prev": null
}
}
Example response (400, Paging, sorting or filtering was requested):
{
"errors": [
{
"status": "400",
"code": "invalid_query",
"title": "Bad Request",
"detail": "This collection is not paginated: every option is returned at once.",
"source": {
"parameter": "page"
}
}
]
}
Example response (401, Missing, invalid or expired token):
{
"errors": [
{
"status": "401",
"code": "invalid_token",
"title": "Unauthenticated"
}
]
}
Example response (403, A named building is not accessible):
{
"errors": [
{
"status": "403",
"code": "building_not_accessible",
"title": "Forbidden",
"detail": "One or more requested buildings are not accessible with this credential.",
"meta": {
"buildings": [
"6650a1f2c4e8b90012ab34c2"
]
}
}
]
}
Example response (403, Cases may not be read in a named building):
{
"errors": [
{
"status": "403",
"code": "forbidden",
"title": "Forbidden",
"detail": "This credential is not permitted to read cases in one or more of the requested buildings."
}
]
}
Example response (422, The credential can reach every building and named none):
{
"errors": [
{
"status": "422",
"code": "validation_failed",
"title": "Unprocessable",
"detail": "Name the buildings whose options to list: this credential can reach every building.",
"source": {
"parameter": "buildings"
}
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List case types
requires authentication
The case types of the buildings where this credential may read cases, ordered by building, then each building's own display order. Every type is returned at once: this collection is not paginated.
Example request:
curl --request GET \
--get "https://keystone.stg.mybos.com/api/v1/case-types?buildings=6650a1f2c4e8b90012ab34c1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Accept: application/json"const url = new URL(
"https://keystone.stg.mybos.com/api/v1/case-types"
);
const params = {
"buildings": "6650a1f2c4e8b90012ab34c1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"type": "case-types",
"id": "6650a2b5c4e8b90012ab3601",
"attributes": {
"name": "Plumbing"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
}
}
},
{
"type": "case-types",
"id": "6650a2b5c4e8b90012ab3602",
"attributes": {
"name": "Electrical"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
}
}
}
],
"meta": {
"total": 2,
"scope": {
"origin": "defaulted"
}
},
"links": {
"self": "/api/v1/case-types",
"first": "/api/v1/case-types",
"next": null,
"prev": null
}
}
Example response (400, Paging, sorting or filtering was requested):
{
"errors": [
{
"status": "400",
"code": "invalid_query",
"title": "Bad Request",
"detail": "This collection is not paginated: every option is returned at once.",
"source": {
"parameter": "page"
}
}
]
}
Example response (401, Missing, invalid or expired token):
{
"errors": [
{
"status": "401",
"code": "invalid_token",
"title": "Unauthenticated"
}
]
}
Example response (403, A named building is not accessible):
{
"errors": [
{
"status": "403",
"code": "building_not_accessible",
"title": "Forbidden",
"detail": "One or more requested buildings are not accessible with this credential.",
"meta": {
"buildings": [
"6650a1f2c4e8b90012ab34c2"
]
}
}
]
}
Example response (403, Cases may not be read in a named building):
{
"errors": [
{
"status": "403",
"code": "forbidden",
"title": "Forbidden",
"detail": "This credential is not permitted to read cases in one or more of the requested buildings."
}
]
}
Example response (422, The credential can reach every building and named none):
{
"errors": [
{
"status": "422",
"code": "validation_failed",
"title": "Unprocessable",
"detail": "Name the buildings whose options to list: this credential can reach every building.",
"source": {
"parameter": "buildings"
}
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List case priorities
requires authentication
The case priorities of the buildings where this credential may read cases, ordered by building, then each building's own display order. Every priority is returned at once: this collection is not paginated.
Example request:
curl --request GET \
--get "https://keystone.stg.mybos.com/api/v1/case-priorities?buildings=6650a1f2c4e8b90012ab34c1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Accept: application/json"const url = new URL(
"https://keystone.stg.mybos.com/api/v1/case-priorities"
);
const params = {
"buildings": "6650a1f2c4e8b90012ab34c1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"type": "case-priorities",
"id": "6650a2c9c4e8b90012ab3701",
"attributes": {
"name": "Urgent"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
}
}
},
{
"type": "case-priorities",
"id": "6650a2c9c4e8b90012ab3702",
"attributes": {
"name": "Low"
},
"relationships": {
"building": {
"data": {
"type": "buildings",
"id": "6650a1f2c4e8b90012ab34c1"
}
}
}
}
],
"meta": {
"total": 2,
"scope": {
"origin": "defaulted"
}
},
"links": {
"self": "/api/v1/case-priorities",
"first": "/api/v1/case-priorities",
"next": null,
"prev": null
}
}
Example response (400, Paging, sorting or filtering was requested):
{
"errors": [
{
"status": "400",
"code": "invalid_query",
"title": "Bad Request",
"detail": "This collection is not paginated: every option is returned at once.",
"source": {
"parameter": "page"
}
}
]
}
Example response (401, Missing, invalid or expired token):
{
"errors": [
{
"status": "401",
"code": "invalid_token",
"title": "Unauthenticated"
}
]
}
Example response (403, A named building is not accessible):
{
"errors": [
{
"status": "403",
"code": "building_not_accessible",
"title": "Forbidden",
"detail": "One or more requested buildings are not accessible with this credential.",
"meta": {
"buildings": [
"6650a1f2c4e8b90012ab34c2"
]
}
}
]
}
Example response (403, Cases may not be read in a named building):
{
"errors": [
{
"status": "403",
"code": "forbidden",
"title": "Forbidden",
"detail": "This credential is not permitted to read cases in one or more of the requested buildings."
}
]
}
Example response (422, The credential can reach every building and named none):
{
"errors": [
{
"status": "422",
"code": "validation_failed",
"title": "Unprocessable",
"detail": "Name the buildings whose options to list: this credential can reach every building.",
"source": {
"parameter": "buildings"
}
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Service
Service status
Whether the service is up and can reach its data. Returns no customer data, so it needs no token.
Example request:
curl --request GET \
--get "https://keystone.stg.mybos.com/api/v1/status" \
--header "Accept: application/json"const url = new URL(
"https://keystone.stg.mybos.com/api/v1/status"
);
const headers = {
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Fully available):
{
"app": true,
"database": true
}
Example response (500, Up, but its data is unreachable):
{
"app": true,
"database": false
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.