Skip to content

API standards

This page outlines the API standards that must be enforced in Autologyx API.

Data types

The data in the API is categorized by type.

TypeNotes
intInteger
uuidUUID
string
url
date
datetime
enumConsists of predefined values
set
bool
email
jsonJSON
userComplex object of system user attributes
user_groupComplex object describing user_group
ownersComplex object describing owners
permissionsComplex object describing permissions

Data structures

If the response schema is complex, the following data structures can be used for categorization. The contents should later be described in a separate table.

In case of less complex nested structures, standard nested.property syntax can be used instead.

TypeNotes
ArrayA JSON array
ObjectA JSON object

User type

Example:

json
{
    "id": 23,
    "first_name": "John",
    "last_name": "Smith",
    "username": "j.smith@autologyx.com",
    "company_name": "Autologyx",
    "is_deleted": false,
    "account_type": "super_admin"
}

Owners type

Type used for resources managed by owners. Value is complex object contains:

  • total number of owners
  • first assigned owner, by added at date and time (user type)

Sample:

json
{
    "total_number": 1,
    "first": {
        "id": 13,
        "first_name": "John",
        "last_name": "Smith",
        "username": "j.smith@autologyx.com",
        "company_name": "Autologyx",
        "is_deleted": false,
        "account_type": "full"
    }
}

Insufficient permissions

ErrorResponse codeMessage
User is authenticated but has not enough permissions to perform method on an endpoint403 Forbidden"detail": "You do not have permission to perform this action."
User has not permission to given resource's instance PK used as value for an400 Bad Request"{attribute}": [ "You do not have permission to use this {resource name}." ]

POST standards

Standard response content

201 Created status code is returned on success.

Error handling

Invalid payload properties

  • Common
ErrorResponse codeMessage
{attribute} is missing400 Bad Request"{attribute}": [ "This field is required." ]
{attribute} is empty string400 Bad Request"{attribute}": [ "This field may not be blank." ]
{attribute} is null400 Bad Request"{attribute}": [ "This field may not be null." ]
{attribute} has > {number} chars400 Bad Request"{attribute}": [ "Ensure this field has no more than {number} characters." ]
{attribute} is not unique400 Bad Request"{attribute}": [ "This field must be unique." ]
{attribute} is null400 Bad Request"{attribute}": [ "This field may not be null." ]
Value for integer field is different type than int400 Bad Request"{attribute}": [ "A valid integer is required."]
Value of different type than list given for list400 Bad Request"{attribute}": [ "Expected a list of items but got type "{type}"." ]
Primary key value for enum {attribute} is different {type} than int400 Bad Request"{attribute}": [ "Incorrect type. Expected pk value, received {type}." ]
{resource} instance for given primary key {value} of enum {attribute} does not exist400 Bad Request"{attribute}": [ "Invalid pk \"{value}\" - {resource} does not exist." ]
User has not perm perm to given resource's instance400 Bad Request"{attribute}": [ "You do not have permission to use this {resource name}." ]
{value} for {attribute} is out of choices400 Bad Request"{attribute}": [ "\"{value}\" is not a valid choice." ]
Max {number} of {resource} exceeded400 Bad Request"detail": "Limit of {number} {resource} has been exceeded.", "error_code": "ERR_LIMIT_EXCEEDED"
Max {number} {sub-resource} per {resource} exceeded400 Bad Request"detail": [ "Limit of {number} {sub-resource} for the {resource} has been exceeded." ]
Insufficient permissions403 Forbidden"detail": "You do not have permission to perform this action."
Resource's instance with "id" does not exist404 Not Found"detail": "Not found."
  • Permission fields
ErrorResponse codeMessage
Invalid {resource} key for permissions400 Bad Request"{attribute}": [ "Invalid resource "{resource}"." ]
Invalid {action} given for resource400 Bad Request"{attribute}": [ ""{action}" is not a valid choice." ]
Value of different type than list given for resource400 Bad Request"{attribute}": [ "Expected a list of items but got type "{type}"." ]
  • File fields
ErrorResponse codeMessage
Invalid file's extension400 Bad Request"detail": [ "File extension “{file_extension}” is not allowed. Allowed extensions are: {allowed_extensions}." ]
Missing header with filename400 Bad Request"detail": [ "Missing filename. Request should include a Content-Disposition header with a filename parameter." ]
File size is over {max} size400 Bad Request"detail": [ "Max file size is {max} MB." ]

Non-modifiable properties

If value for non-modifiable property is given in a request's body, then it is silently ignored.

URL standards

  • URL should contain the dash symbol - instead of underscore _ f.e. /api/endpoint/action-name/

PATCH standards

Standard response content

200 OK status code is returned on success.

Error handling

Invalid IDs in the url

404 Not Found status code is returned on not matching id/uuid.

Invalid payload properties

  • Common
ErrorResponse codeMessage
{attribute} is empty string400 Bad Request"{attribute}": [ "This field may not be blank." ]
{attribute} is null400 Bad Request"{attribute}": [ "This field may not be null." ]
{attribute} has > {number} chars400 Bad Request"{attribute}": [ "Ensure this field has no more than {number} characters." ]
{attribute} is not unique400 Bad Request"{attribute}": [ "This field must be unique." ]
{attribute} is null400 Bad Request"{attribute}": [ "This field may not be null." ]
Value for integer field is different type than int400 Bad Request"{attribute}": [ "A valid integer is required."]
Value of different type than list given for list400 Bad Request"{attribute}": [ "Expected a list of items but got type "{type}"." ]
Primary key value for enum {attribute} is different {type} than int400 Bad Request"{attribute}": [ "Incorrect type. Expected pk value, received {type}." ]
{resource} instance for given primary key {value} of enum {attribute} does not exist400 Bad Request"{attribute}": [ "Invalid pk \"{value}\" - {resource} does not exist." ]
User has not perm perm to given resource's instance400 Bad Request"{attribute}": [ "You do not have permission to use this {resource name}." ]
{value} for {attribute} is out of choices400 Bad Request"{attribute}": [ "\"{value}\" is not a valid choice." ]
Max {number} of {resource} exceeded400 Bad Request"detail": "Limit of {number} {resource} has been exceeded.", "error_code": "ERR_LIMIT_EXCEEDED"
Max {number} {sub-resource} per {resource} exceeded400 Bad Request"detail": [ "Limit of {number} {sub-resource} for the {resource} has been exceeded." ]
Insufficient permissions403 Forbidden"detail": "You do not have permission to perform this action."
Resource's instance with "id" does not exist404 Not Found"detail": "Not found."
  • Permission fields
ErrorResponse codeMessage
Invalid {resource} key for permissions400 Bad Request"{attribute}": [ "Invalid resource "{resource}"." ]
Invalid {action} given for resource400 Bad Request"{attribute}": [ ""{action}" is not a valid choice." ]
Value of different type than list given for resource400 Bad Request"{attribute}": [ "Expected a list of items but got type "{type}"." ]
  • File fields
ErrorResponse codeMessage
Invalid file type400 Bad Request"{attribute}": [ "Invalid file type." ]

Non-modifiable properties

If value for non-modifiable property is given in a request's body, then it is silently ignored.

Preventing some fields to be updated

Some fields can be set during creation, but they cannot be changed via PATCH.

Instead of handling errors on fields used with Create request we should use apps.api.mixins.CreateOnlyFieldsMixin.

By adding it as a mixing to a serializer, we force silently ignore this field in the update request.

python
class ObjectClassFormDetailSerializer(CreateOnlyFieldsMixin, ...):
    ...
    class Meta:
        ...
        create_only_fields = (
            'object_class',
            'type',
        )

GET standards

In most cases, the GET method can return:

  • list of items
  • single item (detail, with extended set of attributes)

Common (list and detail)

Serializer's text fields with empty values

Text fields, like description should allow empty string (""). NULL values are not accepted, even if model accepts them. Existing NULL values should be serialized as empty strings.

python
description = serializers.CharField(..., default="")

Labels

If list request (like /api/task-templates/) data for given property of type set or enum is dispalyed in response json as a list of integers (idents of related objects):

json
"task_templates": [1, 2],

then details request (like /api/task-templates/{id}/) data for given property of type set or enum is displayed in the same format as a list of integers(idents of related objects):

json
"task_templates": [1, 2],

API will deliver details in additional helper parameter _meta

json
"_meta": {
    "labels": {
        "task_templates": [
            "task template name 1",
            "task template name 2",
        ]
    }
}

List standards

Filtering predicates

Legend:

  • + - operator available for specific data type
  • c.ins. - case insensitive
PredicateOperatorintuuidstringurldatedatetimeenumsetboolphoneemailuserowners
Equal=+++++++++++++
Equal (c.ins.)iexact=++++
Is Emptyisempty=++++
Containscontains=++++
Contains (c.ins.)icontains=++++
Starts withstartswith=++++
Starts with (c.ins.)istartswith=++++
Ends withendswith=++++
Ends with (c.ins.)iendswith=++++
Is NULLisnull=+++++++
Lower thanlt=+++
Lower/equal thanlte=+++
Greater thangt=+++
Greater/equal thangte=+++
Rangerange=+++
Is inin=+++
Contains allcontainsall=+
Contains somecontainssome=+

Filtering by primary key of integer type does not support isnull operator due to primary key cannot be NULL.

Relational complex fields like created_by, modified_by will not be sortable because we expect performance decrease. Fields are annotated to response queryset with complex database operations.

Operator should be used with attribute's name:

  • name=
  • name__startswith=
  • created_at__gte=

To negate an operator, please use !

  • name!=
  • name__endswith!=
  • count__lt!=

Sample: /api/object-classes/?id__gte=2005

Error handling

ErrorResponse codeMessage
Value for filtering by enum {parameter} is out of choices400 Bad Request"{parameter}": [ "Select a valid choice. That choice is not one of the available choices." ]
{value} for filtering by set {parameter} is out of choices400 Bad Request"{parameter}": [ "“"{value}"” is not a valid value." ]
Value for filtering by date/time {parameter} is invalid400 Bad Request"{parameter}": [ "Enter a valid date/time." ]
{value} for ordering is out of available parameters400 Bad Request"ordering": [ "Select a valid choice. {value} is not one of the available choices." ]

Detail standards

Invalid IDs in the url

404 Not Found status code is returned on not matching id/uuid.

DELETE standards

Standard response content

204 No Content response status code.

Response body is empty.

Error handling

Invalid IDs in the url

404 Not Found status code is returned on not matching id/uuid.

OPTIONS standards

Status code

200 OK status code is returned on success.

Response structure

Response is a JSON object with following attributes:

  • list
  • details
  • restrictions
json
{
    "list": {
        "columns": [...]
    },
    "details": {
        "schema": [...]
    },
    "restrictions": {
        "limit_items": 10000
    }
}

Each of the above attributes is optional, it's presence depends on API endpoint being implemented (list or details) and having any limitations (restrictions).

list attribute

Contains information related to API list view e.g. /api/task-templates/

list.columns attribute

It’s a list of fields available for the listing view with information if sorting or filtering is possible for given field or not.

json
"columns": [
    {
        "alias": <string>,
        "type": <type>,
        "predicates": [<string>, ...],
        "sort_ok": <bool>
    },
    ...
]

Each field (irrespectively of type) is represented by JSON object with following attributes:

  • alias – field alias used to build filtering and sorting queries
  • type – field type
  • predicates – list with available predicates for filtering, if empty then filtering is not allowed
  • sort_ok – boolean flag determining if sorting is allowed

Additionally, fields of enum and set types may have additional keys:

  • values – list of JSON objects with predefined values for the field:
json
"values": [
    {
        "value": <value>,
        "text": <label>
    },
    ...
]
  • autocomplete – relative URL to API endpoint where available values can be obtained

Sample:

json
"columns": [
    {
        "alias": "id",
        "type": "int",
        "predicates": [
            "exact",
            "gt",
            "gte",
            "lt",
            "lte",
            "range"
        ],
        "sort_ok": true
    },
    {
        "alias": "task_group_templates",
        "type": "enum",
        "predicates": [
            "isnull",
            "containsall",
            "containssome"
        ],
        "sort_ok": false,
        "autocomplete": "/api/task-group-templates/autocomplete/?text__icontains="
    },
    {
        "alias": "status",
        "type": "enum",
        "predicates": [
            "exact"
        ],
        "sort_ok": false,
        "values": [
            {
                "value": 1,
                "text": "Active"
            },
            {
                "value": 2,
                "text": "Archived"
            }
        ]
    },
]

details attribute

Contains information related to API detail view e.g. /api/task-templates/{id}/.

details.schema attribute

It’s a list of JSON objects that can be of two types:

  • Field – represents single field
  • Nested schema – represents multiple fields as nested group (more can be found in Task Templates - JSON schema for OPTIONS request )
Fields

Field object contain requirements around the field for the create and detail views.

json
"schema": [
    {
        "alias": <string>,
        "type": <type>,
        "required": <bool>
    },
...
]

Each field (irrespectively of type) is represented by JSON object with following attributes:

  • alias – field alias
  • type – field type
  • required - boolean flag determining if field is required

Optionally following attributes may be used:

  • validators – list of validators that checks if value is correct:
json
"validators": [<json>, <json>, ...]

Where each validator has at least one attribute type and depending on it’s type additional attributes:

json
{
    "type": <string>,
    ...
}

Supported validators:

TypeOptionsDescription
min_lengthminimal number of charactersValidates min length of string
max_lengthmaximum number of charactersValidates max length of string
min_valueminimal allowed valueValidates min value of number
max_valuemaximum allowed valueValidates max value of number
date_in_futureValidates if date is in the future

Additionally, fields of type enum and set may have:

  • values – list of JSON objects with predefined values for the field:
json
"values": [
    {
        "value": <value>,
        "text": <string>
    },
    ...
]
  • autocomplete - relative URL to API endpoint where available values can be obtained.

Sample:

json
"schema": [
    {
        "alias": "name",
        "type": "string",
        "required": true,
        "validators": [
            {
                "type": "min_length",
                "length": 1
            },
            {
                "type": "max_length",
                "length": 255
            }
        ]
    },
    {
        "alias": "time_unit",
        "type": "enum",
        "required": true,
        "values": [
            {
                "value": "days",
                "text": "days"
            },
            {
                "value": "weeks",
                "text": "weeks"
            },
            {
                "value": "months",
                "text": "months"
            }
        ]
    },
    ...
]
Nested schema
json
"schema": [ 
    { 
        "alias": <string>, 
        "schema": [<json>, ...]
    }, 
    ... 
]

Aggregates multiple fields as nested JSON object. Always contains at least two attributes:

  • alias – alias of a group
  • schema – list of fields or another nested schema

Optionally following attributes may be used:

  • schema_by_&lt;alias&gt; – similar to schema attribute but used when schema depends on value of another field.
  • validators – list of validators that checks if entire group of fields is correct.
Schema by value from different field

schema_by_&lt;alias&gt; - alias is a name of a field on which value a schema depends.

Define the schema of a field when schema depends on another field's value.

At least two obligatory attributes are present:

  • alias - field name which value affects the schema ("task_type" in the below example)
  • schema – list of fields in the schema

Sample:

json
{
    "alias": "plugin_config",
    "schema": [
        {
            "alias": "task_type",
            "type": "string",
            "required": true,
            "values": [
                {
                    "value": "tt_form",
                    "text": "Form"
                }
            ]
        }
    ],
    "schema_by_type": [
        {
            "task_type": "tt_form",
            "schema": [
                {
                    "alias": "task_type",
                    "schema": [
                        {
                            "alias": "data_type",
                            "type": "string",
                            "required": true,
                            "values": [
                                {
                                    "value": "t_form",
                                    "text": "Form"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

If a validator apply to only some Fields in the group an apply_to attribute is used to point which Fields are affected.

Supported validators:

TypeOptionsDescription
max_lengthmaximal number of items in the groupValidates maximal number of items in the group

Example:

json
{
    "alias": "reminders",
    "schema": [
        {
            "alias": "notice_type",
            "type": "enum",
            "required": true,
            "values": [
                {
                    "value": "task_complete_by",
                    "text": "Task to Complete by"
                },
                {
                    "value": "task_overdue",
                    "text": "Task Overdue"
                },
                ...
            ]
        }
    ],
    "validators": [
        {
            "type": "max_length",
            "length": 1,
            "apply_to": {
                "alias": "notice_type",
                "value": "task_complete_by"
            }
        },
        {
            "type": "max_length",
            "length": 10,
            "apply_to": {
                "alias": "notice_type",
                "value": "task_overdue"
            }
        },
        ...
    ]
}

For above example:

  • Only 1 reminder of notice_type=”task_complete_by” is allowed
  • Maximum 10 reminders of notice_type=”task_overdue” are allowed

restrictions attribute

Contains all kinds of limitations that are enforced for particular endpoint.

Autocomplete

Some related api endpoint uses data stored as an enum or set type. OPTIONS request will contain an autocomplete relative url like: /api/users/autocomplete/. Only GET request to this endpoint is avaliable

Restrictions based on limits

When some endpoint is limited by number of objects to create, the response should be:

HTTP 403 Forbidden

with response body:

json
{
    "detail": "Limit of {limit} {object_name} has been exceeded.",
    "error_code": "ERR_LIMIT_EXCEEDED"
}