Introduction
Welcome to the Carium API, which uses REST and JSON:API to support a wide range of functionality. While most endpoints return JSON-encoded responses, attachments can be retrieved directly. Any exceptions are noted for that specific endpoint. The API uses standard HTTP response codes, authentication, and verbs. All calls must be made over HTTPS.
The root of all API calls is https://api.carium.com
. Most API endpoints are versioned, and you should always use the
latest version available.
Authentication
Users must authenticate with /identity/v1/login/
to access the Carium API. Access to APIs are then granted by passing
your access-token
in the request as a Bearer
token in the authorization header.
Example call with auth
curl -X 'GET' \
'https://api.carium.com/caredb/v1/journal-entries/' \
-H 'accept: application/vnd.api+json' \
-H 'authorization: Bearer <<access-token>>'
Most endpoints in the Carium API require the user to be authenticated. Unless otherwise noted, assume the access token should be passed in the header.
Error Handling
Carium uses standard HTTP response codes to indicate success or failure of a request. Additionally, some responses include custom error information to allow the caller to resolve the error programmatically or provide a better user experience.
Formats
Some data types returned by the API can not be natively represented in JSON. These types are returned as strings in a
specified format -- represented as {"type": "string", "format": "<format>"}
. The following types will be frequently
returned or taken as input:
date
- A date represented as a string in the formatYYYY-MM-DD
.datetime
- A date and time represented as a string in the formatYYYY-MM-DD hh:mm:ss
. This is in UTC unless otherwise noted. For input, one may also specify the value as an RFC-3339 timestamp. However, responses will always be in the formatYYYY-MM-DD hh:mm:ss
.email
- An email address that follows the RFC-2822 formatphonenumberE164
- A phone-number represented as a string in the E.164 format.uuid
- A universally unique identifier represented as a string in the UUID formatxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
. Unless otherwise noted, these may be parsed by clients into a native UUID type and stored as a 128-bit integer.
Paging
Carium supports paging for many of the endpoints. When paging is supported, two optional properties:
Property | Default | Description |
---|---|---|
page[limit] | varies | The maximum number of records returned per page |
page[offset] | 0 | The starting index of the returned records |
Additionally, the top-level 'meta' object contains paging information:
Property | Description |
---|---|
page[offset] | The starting index of the returned records |
page[limit] | The maximum number of records returned per page |
page[total] | The total number of records that match the criteria |
Rate Limits
Requests are metered per-user and a usage quota is enforced. If no authentication information is provided, requests are metered per-IP address.
Clients may view rate limit quota consumption by reading the X-Ratelimit-*
headers:
Header | Type | Description |
---|---|---|
X-Ratelimit-Limit | int | Rate limit quota. |
X-Ratelimit-Used | int | Used quota in the current time bucket. |
X-Ratelimit-Remaining | int | Remaining quota used in current time bucket. |
X-Ratelimit-Reset | int | Unix timestamp when fresh quota will be available. UTC. |
Clients exceeding rate limit quotas will be throttled with HTTP 429 Too Many Requests
. The response will
include Retry-After advisement. Clients should
defer additional requests until the time specified to avoid further throttling.
Rate limit quota increases may be requested by contacting support.
Conventions
Standards
- Carium API follows JSON API specification to specify the JSON request/response structure
- Carium API uses token instead of cookies (Cookies vs Tokens)
- HTTP Protocol: RFC-7231
Additional Requirements
On top of JSON API spec, Carium API adds additional requirements that are necessary, which includes:
-
Path should be in the form of
/<appname>/<version>/<resources>/
.Examples:
/myapp/v1/tests/
/yourapp/v3/tickets/
-
Resource object identification should be plural.
Examples:
http://site.app.carium.com/identity/v1/users/
http://site.app.carium.com/identity/v1/groups/
-
For action that doesn’t fall within POST/GET/PATCH/DELETE, Carium API supports custom methods that follows the resource specific id (JSON API currently doesn't specify how it should be done). The custom-method must be in a verb form.
Examples:
http://abc.com/identity/v1/tests/1/reset/
http://abc.com/identity/v1/tests/11-22-33-44/reset/
-
Carium API doesn't support global action directly on top of the resources (example:
/identity/api/v1/tests/reset
) to avoid ambiguity. -
Carium API enforces trailing slash at the end of the path. If the client calls the endpoint without trailing slash, the server will redirect them to the correct one.
Request Parameters
Depending on the HTTP method, Carium API can pass request parameters to the API server using query-string and content/body.
Even though RFC-7231 section 4.3 provides a lot of flexibility on which method to use, to standardize the API implementation, Carium uses:
- Query String, only for
GET
andDELETE
- Content/Body for other methods (
PATCH
,POST
,PUT
)
Carium API uses Query String for GET/DELETE to maintain compatibility with other existing implementations (as explained in the RFC). Note that Query String has size-limit (around 4KB, depending on the browser and the web server).
If the API requires larger parameter size, Carium will use other method (for example POST
).
Naming
Carium API follows the JSON API restrictions for member names. However, since JSON API doesn’t explicitly mention the naming style for attributes and to keep consistencies, all Carium APIs use Kebab Case, which aligns well with the JavaScript convention.
This style applies to:
- Query parameters
- JSON attribute names, both request and response
- URL path
{
"meta": {
"page[offset]": 0,
"page[limit]": 100
}
}
Filtering
Reference: https://jsonapi.org/format/#fetching-filtering https://jsonapi.org/format/1.1/#query-parameters
filter[field]
: The value type is based on the field's value
The filter[field]
is used for exact match (case insensitive, due to database limitation).
In the case where it’s necessary additional operator comparison (for example gt
, lt
, contains
), extend the filter
by adding -<operator
.
Example:
filter[name]=abc
is searching for all objects with name exactly abc
filter[type]=xyz
is searching for all objects with type exactly xyz
filter[name][contains]=abc
is searching for all objects that has abc
in the name
filter[count][gt]=10
is searching for all objects with count more than 10
filter[date][gte]=2021-09-23
is searching for all objects with date equal to or after 2021-09-23
Valid operators: gt
, gte
, lt
, lte
, contains
Datetime filtering:
Although it’s possible to use an option such as filter[datetime][gte]=2021-09-23 00:00:00
, Carium API adopted a
flexible cmp- formula. The parameter template is <operator>-<datetime>
where operator can be one of >
, <
, >=
,
<=
. The equivalent filter in the cmp- style would be:
filter[cmp-datetime]=>=2021-09-23 00:00:00
AND vs OR
AND operations are accomplished by including multiple & separated filter
statements. In the case where the same
filter can be repeated this is seen as an array type option. E.g.:
filter[cmp-start-at]=>=2021-09-23 00:00:00&filter[cmp-start-at]=<2021-09-24 00:00:00
OR operations can be accomplished for a single filter with comma separated values.
Specifically this can be applied for complex datetime filtering to allow for null values:
filter[cmp-datetime]=>=2021-09-23 00:00:00,null
Note on field
vs filter[field]
parameter name:
field
is used for a required field. For example, when a client calls list
API, it’s often required to pass an
organization filter. In this case, the parameter should be organization-id
.
Nullable
There are some conflicts in regards to specify if an argument is nullable or not. This case is useful when the API allows a user to reset a certain attribute, while enforcing the formatter on that argument.
For example: specifying a phone attribute with e164 format, but also allow an empty value to nullify/reset this attribute.
While Swagger OpenAPI 3.0 supports the Nullable
type, OpenAPI 3.1 drops that support in favor of json-schema compatible oneOf
flavor.
The preferred nullable definition would be:
"expire-time": {
"oneOf": {
{"type": "null"},
{"type": "string", "format": "datetime"},
}
}
Sorting
Reference: https://jsonapi.org/format/#fetching-sorting
sort: Array(String(enum=[]), min_items=1)
Different than the spec, sort uses array structure to indicate multiple sort fields. For example: service1/v1/objects?sort=field1&sort=field2
Error
Reference: https://jsonapi.org/format/#errors
Example:
{
"errors": [
{
"status": "400",
"detail": "User is not in confirmed state",
"code": "UserDisabledError",
"meta": { "key": "value" }
}
]
}
meta
attribute is optional.
Status Code
200
: Default return value for GET and PUT when operation was successful.201
: Used for POST when operation was successful.202
: Used for POST, PUT, DELETE, when operation was pending and result isn’t yet available.204
: Used for DELETE when there is no content to return.400
: Common response for user error. Ideally, user should be able to change their request parameters to fix this error.403
: Error response for access denied.404
: Error response for resource not found.500
: Internal server error. This is the default error when the server finds an unhandled exception. The client shouldn’t see this error.
Philosophies
In general at HTTP interfaces between applications the Carium API follows the robustness principle to ensure loose coupling between the Carium applications.