The API has an REST/RPC-ish style, and authentication/authorization uses a JSON Web Token (JWT) so we don't have server-side state.
The API is JSON based, where we send all parameters as a POST body in JSON, and all responses (except http status ones) are in JSON too. If we make a call without parameters, we'll do a GET (these are rare).
Request JSON usually has the form
{
<name>: <value>,
"language": "en",
…
}
Which arguments we can or must provide is specific to the endpoint we are calling.
Response JSON is formed
{
"success": true | false,
"result": info | error,
"data": {}
}
If success
is true
, result
is a dictionary dependent on the call, where each property holds references in the form of global identifiers (gids). The data
property fulfills these references per resource type.
If success
is false
, data
is empty, and result
is of the form
{
"code": 400,
"message": "Bad request",
"info": {}
}
For the error code
, we use http status codes for http errors, and 1000 and up for app-specific errors, starting with a generic 1000 - Unexpected error. The info
property holds associated error info, object form is defined by the error code.
The error codes are enumerated:
# http - all codes should match http status codes
# messages may vary
BAD_REQUEST = (400, "Bad request")
PERMISSION_DENIED = (401, "Unauthorized")
FORBIDDEN = (403, "Forbidden")
UNKNOWN_USER = (403, "Unknown user")
UNPROCESSABLE_ENTITY = (422, "Unprocessable Entity")
INTERNAL_SERVER_ERROR = (500, "Internal server error")
NOT_IMPLEMENTED = (501, "Not implemented")
# app - codes starting from 1000, outside http status code range
UNEXPECTED = (1000, "Unexpected error")
VALIDATION = (1001, "Validation error")
SEARCH = (1002, "Search error")
PROCESS = (1003, "Process error")
INVITE_INVALID = (1004, "Invite invalid")
An example of a successful request with response:
POST https://unicat.app/api/p/<project_gid>/records/get
Authorization: Bearer <jwt>
{
"record": "4aa680cf-b43e-4769-bd09-5d298abbcac7",
"language": "nl"
}
{
"success": true,
"result": {
"record": "4aa680cf-b43e-4769-bd09-5d298abbcac7"
},
"data": {
"records": {
"4aa680cf-b43e-4769-bd09-5d298abbcac7": {
"gid": "4aa680cf-b43e-4769-bd09-5d298abbcac7",
"canonical": "4aa680cf-b43e-4769-bd09-5d298abbcac7",
"parent": "f2e64fe0-9ffa-4d9a-8750-d561d6542453",
…,
"fields": {
"nl": {
"name": "IJsconservatoren",
"image": "71f85042-7d1e-4f62-b157-2a3aa3105412",
"description": "IJsconservatoren, vrieskisten en accessoires. De ideale opslag voor al uw diepvries producten.",
…
}
}
}
}
}
}
An example of a failed request with response:
POST https://unicat.app/api/p/<project_gid>/records/get
Authorization: Bearer <jwt>
{
"missing-record": "4aa680cf-b43e-4769-bd09-5d298abbcac7",
"language": "nl"
}
{
"success": false,
"result": {
"code": 400,
"message": "Bad request",
"info": {}
},
"data": {}
}
A list of the data resource types and their structures
Global
cc.users
User info like name, email, avatar.
cc.projects
Project info like name, owner, channels.
cc.projects_members
Member info per project, like status, roles.
cc.languages
Available languages for internationalization and localization.
Per project
records
Record info with hierarchy, definition, field values.
definitions
Definition info with name, classes, fields.
classes
Class info with name, fields.
fields
Field info with name, type, options.
layouts
Layout info with hierarchy.
assets
Asset info with hierarchy, type, name.
queries
Query info with type, name, q, and filter.