API standards
This page defines the platform-wide API standards used across Autologyx.
These standards exist so that APIs behave consistently across services, resources, and endpoints. They help ensure that request and response structures are predictable, validation behaviour is consistent, filtering and sorting rules are reusable, and error messages can be interpreted reliably by both users and client applications.
Why standards matter
Autologyx APIs are used across many different areas of the platform, including configuration, workflow execution, integrations, permissions, event handling, and operational services. Without a shared standard, each endpoint could behave differently, making integrations harder to build, maintain, and support.
By applying consistent API standards, Autologyx aims to provide:
- predictable request and response behaviour
- consistent validation and error handling
- reusable filtering, sorting, and schema conventions
- clearer expectations for integrators and internal developers
- a more maintainable platform over time
Strong typing in the Autologyx API
The Autologyx API takes a strongly typed approach to data.
This means that fields, payload attributes, filters, and schema definitions are expected to have clear and well-defined types. Rather than treating values as loosely structured data wherever possible, the platform distinguishes explicitly between integers, UUIDs, strings, booleans, enums, sets, dates, datetimes, JSON objects, and more complex structured types such as users, owners, and permissions.
In practice, this means:
- values are validated according to their defined type
- invalid data types are rejected with explicit errors
- related resources and enumerated values are handled consistently
- schemas describe both which fields exist and what kind of data each field accepts
- client applications can rely on a stable contract when integrating with the platform
This strongly typed approach reduces ambiguity, makes integrations safer, and supports more reliable platform behaviour across both UI-driven and API-driven workflows.
How to use this page
Use this page as the baseline reference for designing, reviewing, or implementing Autologyx API endpoints.
It describes the platform-wide rules for:
- data types and structures
- request and response conventions
- validation and error handling
- filtering and sorting behaviour
- schema definitions used in
OPTIONSresponses - endpoint restrictions and common response patterns
Data types
The API data model uses explicit types so that values can be validated, documented, and handled consistently.
| Type | Notes |
|---|---|
| int | Integer |
| uuid | UUID |
| string | Text value |
| url | URL value |
| date | Date value |
| datetime | Date and time value |
| enum | Consists of predefined values |
| set | Collection of predefined values |
| bool | Boolean value |
| Email address | |
| json | JSON |
| user | Complex object of system user attributes |
| user_group | Complex object describing a user group |
| owners | Complex object describing owners |
| permissions | Complex object describing permissions |
Data structures
Where response schemas are more complex, the following structural categories can be used.
For simpler nested structures, standard nested.property syntax can be used instead.
| Type | Notes |
|---|---|
| Array | A JSON array |
| Object | A JSON object |
User type
Example:
{
"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
The owners type is used for resources managed by owners. The value is a complex object containing:
- the total number of owners
- the first assigned owner, based on the date and time it was added
Example:
{
"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
Use the following responses when a user is authenticated but does not have the required permissions.
| Error | Response code | Message |
|---|---|---|
| User is authenticated but does not have permission to perform the method on an endpoint | 403 Forbidden | "detail": "You do not have permission to perform this action." |
| User does not have permission for a resource instance used as the value of an attribute | 400 Bad Request | "{attribute}": [ "You do not have permission to use this {resource name}." ] |
POST standards
POST endpoints are used for creation operations and should return 201 Created on success unless there is a documented exception.
Standard response content
- Success status:
201 Created
Error handling
Invalid payload properties
Common
| Error | Response code | Message |
|---|---|---|
{attribute} is missing | 400 Bad Request | "{attribute}": [ "This field is required." ] |
{attribute} is an empty string | 400 Bad Request | "{attribute}": [ "This field may not be blank." ] |
{attribute} is null | 400 Bad Request | "{attribute}": [ "This field may not be null." ] |
{attribute} has more than {number} characters | 400 Bad Request | "{attribute}": [ "Ensure this field has no more than {number} characters." ] |
{attribute} is not unique | 400 Bad Request | "{attribute}": [ "This field must be unique." ] |
| Value for an integer field is not an integer | 400 Bad Request | "{attribute}": [ "A valid integer is required." ] |
Value of a different type than list is supplied for list {attribute} | 400 Bad Request | "{attribute}": [ "Expected a list of items but got type "{type}"." ] |
Primary key value for enum {attribute} is of type {type} instead of int | 400 Bad Request | "{attribute}": [ "Incorrect type. Expected pk value, received {type}." ] |
{resource} instance for primary key {value} of enum {attribute} does not exist | 400 Bad Request | "{attribute}": [ "Invalid pk "{value}" - {resource} does not exist." ] |
| User does not have permission to use a given resource instance | 400 Bad Request | "{attribute}": [ "You do not have permission to use this {resource name}." ] |
{value} for {attribute} is out of choices | 400 Bad Request | "{attribute}": [ ""{value}" is not a valid choice." ] |
Max {number} of {resource} exceeded | 400 Bad Request | "detail": "Limit of {number} {resource} has been exceeded.", "error_code": "ERR_LIMIT_EXCEEDED" |
Max {number} {sub-resource} per {resource} exceeded | 400 Bad Request | "detail": [ "Limit of {number} {sub-resource} for the {resource} has been exceeded." ] |
| Insufficient permissions | 403 Forbidden | "detail": "You do not have permission to perform this action." |
Resource instance with "id" does not exist | 404 Not Found | "detail": "Not found." |
Permission fields
| Error | Response code | Message |
|---|---|---|
Invalid {resource} key for permissions {attribute} | 400 Bad Request | "{attribute}": [ "Invalid resource "{resource}"." ] |
Invalid {action} given for resource | 400 Bad Request | "{attribute}": [ ""{action}" is not a valid choice." ] |
| Value of different type than list given for resource | 400 Bad Request | "{attribute}": [ "Expected a list of items but got type "{type}"." ] |
File fields
| Error | Response code | Message |
|---|---|---|
| Invalid file extension | 400 Bad Request | "detail": [ "File extension “{file_extension}” is not allowed. Allowed extensions are: {allowed_extensions}." ] |
| Missing header with filename | 400 Bad Request | "detail": [ "Missing filename. Request should include a Content-Disposition header with a filename parameter." ] |
File size is over {max} | 400 Bad Request | "detail": [ "Max file size is {max} MB." ] |
Non-modifiable properties
If a value for a non-modifiable property is supplied in the request body, it should be silently ignored unless the endpoint explicitly documents a different behaviour.
URL standards
URLs should use hyphens (-) rather than underscores (_).
Example:
/api/endpoint/action-name/PATCH standards
PATCH endpoints are used for partial updates and should return 200 OK on success unless there is a documented exception.
Standard response content
- Success status:
200 OK
Error handling
Invalid IDs in the URL
If the id or uuid in the URL does not match a resource, return:
404 Not Found
Invalid payload properties
Common
| Error | Response code | Message |
|---|---|---|
{attribute} is an empty string | 400 Bad Request | "{attribute}": [ "This field may not be blank." ] |
{attribute} is null | 400 Bad Request | "{attribute}": [ "This field may not be null." ] |
{attribute} has more than {number} characters | 400 Bad Request | "{attribute}": [ "Ensure this field has no more than {number} characters." ] |
{attribute} is not unique | 400 Bad Request | "{attribute}": [ "This field must be unique." ] |
| Value for an integer field is not an integer | 400 Bad Request | "{attribute}": [ "A valid integer is required." ] |
Value of a different type than list is supplied for list {attribute} | 400 Bad Request | "{attribute}": [ "Expected a list of items but got type "{type}"." ] |
Primary key value for enum {attribute} is of type {type} instead of int | 400 Bad Request | "{attribute}": [ "Incorrect type. Expected pk value, received {type}." ] |
{resource} instance for primary key {value} of enum {attribute} does not exist | 400 Bad Request | "{attribute}": [ "Invalid pk "{value}" - {resource} does not exist." ] |
| User does not have permission to use a given resource instance | 400 Bad Request | "{attribute}": [ "You do not have permission to use this {resource name}." ] |
{value} for {attribute} is out of choices | 400 Bad Request | "{attribute}": [ ""{value}" is not a valid choice." ] |
Max {number} of {resource} exceeded | 400 Bad Request | "detail": "Limit of {number} {resource} has been exceeded.", "error_code": "ERR_LIMIT_EXCEEDED" |
Max {number} {sub-resource} per {resource} exceeded | 400 Bad Request | "detail": [ "Limit of {number} {sub-resource} for the {resource} has been exceeded." ] |
| Insufficient permissions | 403 Forbidden | "detail": "You do not have permission to perform this action." |
Resource instance with "id" does not exist | 404 Not Found | "detail": "Not found." |
Permission fields
| Error | Response code | Message |
|---|---|---|
Invalid {resource} key for permissions {attribute} | 400 Bad Request | "{attribute}": [ "Invalid resource "{resource}"." ] |
Invalid {action} given for resource | 400 Bad Request | "{attribute}": [ ""{action}" is not a valid choice." ] |
| Value of different type than list given for resource | 400 Bad Request | "{attribute}": [ "Expected a list of items but got type "{type}"." ] |
File fields
| Error | Response code | Message |
|---|---|---|
| Invalid file type | 400 Bad Request | "{attribute}": [ "Invalid file type." ] |
Non-modifiable properties
If a value for a non-modifiable property is supplied in the request body, it should be silently ignored unless the endpoint explicitly documents a different behaviour.
Preventing some fields from being updated
Some fields can be set during creation but cannot be changed via PATCH.
Instead of returning an error for fields that are only valid during creation, use apps.api.mixins.CreateOnlyFieldsMixin.
By adding the mixin to a serializer, the update request will silently ignore those fields.
class ObjectClassFormDetailSerializer(CreateOnlyFieldsMixin, ...):
...
class Meta:
...
create_only_fields = (
'object_class',
'type',
)GET standards
In most cases, the GET method can return:
- a list of items
- a single item in detail form, with an extended set of attributes
Common standards for list and detail views
Serializer text fields with empty values
Text fields such as description should allow an empty string (""). NULL values are not accepted, even if the underlying model allows them. Existing NULL values should be serialized as empty strings.
description = serializers.CharField(..., default="")Labels
If a list request, for example /api/task-templates/, returns a property of type set or enum as a list of integers representing related object IDs:
"task_templates": [1, 2]then the detail request for the same resource, for example /api/task-templates/{id}/, should return the same property in the same format:
"task_templates": [1, 2]Additional labels should be provided in the helper _meta parameter:
"_meta": {
"labels": {
"task_templates": [
"task template name 1",
"task template name 2"
]
}
}List standards
Filtering predicates
Legend:
+- operator available for the specific data typec.ins.- case insensitive
| Predicate | Operator | int | uuid | string | url | date | datetime | enum | set | bool | phone | user | owners | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Equal | = | + | + | + | + | + | + | + | + | + | + | + | + | + |
| Equal (c.ins.) | iexact= | + | + | + | + | |||||||||
| Is Empty | isempty= | + | + | + | + | |||||||||
| Contains | contains= | + | + | + | + | |||||||||
| Contains (c.ins.) | icontains= | + | + | + | + | |||||||||
| Starts with | startswith= | + | + | + | + | |||||||||
| Starts with (c.ins.) | istartswith= | + | + | + | + | |||||||||
| Ends with | endswith= | + | + | + | + | |||||||||
| Ends with (c.ins.) | iendswith= | + | + | + | + | |||||||||
| Is NULL | isnull= | + | + | + | + | + | + | + | ||||||
| Lower than | lt= | + | + | + | ||||||||||
| Lower/equal than | lte= | + | + | + | ||||||||||
| Greater than | gt= | + | + | + | ||||||||||
| Greater/equal than | gte= | + | + | + | ||||||||||
| Range | range= | + | + | + | ||||||||||
| Is in | in= | + | + | + | ||||||||||
| Contains all | containsall= | + | ||||||||||||
| Contains some | containssome= | + |
Filtering by primary key of integer type does not support isnull because a primary key cannot be NULL.
Relational complex fields such as created_by and modified_by should not be sortable, because they require complex queryset annotations and may cause performance degradation.
Operator examples:
name=name__startswith=created_at__gte=
To negate an operator, use !:
name!=name__endswith!=count__lt!=
Example:
/api/object-classes/?id__gte=2005Error handling
| Error | Response code | Message |
|---|---|---|
Value for filtering by enum {parameter} is out of choices | 400 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 choices | 400 Bad Request | "{parameter}": [ "“"{value}"” is not a valid value." ] |
Value for filtering by date/time {parameter} is invalid | 400 Bad Request | "{parameter}": [ "Enter a valid date/time." ] |
{value} for ordering is out of available parameters | 400 Bad Request | "ordering": [ "Select a valid choice. {value} is not one of the available choices." ] |
Detail standards
Invalid IDs in the URL
If the id or uuid in the URL does not match a resource, return:
404 Not Found
DELETE standards
DELETE endpoints should return 204 No Content on success.
Standard response content
- Success status:
204 No Content - Response body: empty
Error handling
Invalid IDs in the URL
If the id or uuid in the URL does not match a resource, return:
404 Not Found
OPTIONS standards
OPTIONS endpoints provide machine-readable metadata about list views, detail schemas, and endpoint restrictions.
Status code
- Success status:
200 OK
Response structure
The response is a JSON object with the following attributes:
listdetailsrestrictions
{
"list": {
"columns": [...]
},
"details": {
"schema": [...]
},
"restrictions": {
"limit_items": 10000
}
}Each of the above attributes is optional. Their presence depends on the API endpoint being implemented (list or details) and whether any restrictions apply.
list attribute
Contains information related to the API list view, for example /api/task-templates/.
list.columns attribute
This is a list of fields available in the list view, including whether sorting or filtering is supported.
"columns": [
{
"alias": "<string>",
"type": "<type>",
"predicates": ["<string>", "..."],
"sort_ok": "<bool>"
}
]Each field, regardless of type, is represented by a JSON object with the following attributes:
alias– field alias used to build filtering and sorting queriestype– field typepredicates– list of available filtering predicates; if empty, filtering is not allowedsort_ok– boolean flag indicating whether sorting is allowed
Additionally, fields of type enum and set may have:
values– list of JSON objects with predefined values for the fieldautocomplete– relative URL to an API endpoint where available values can be obtained
Example:
"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 the API detail view, for example /api/task-templates/{id}/.
details.schema attribute
This is a list of JSON objects of two possible kinds:
- Field – represents a single field
- Nested schema – represents multiple fields grouped as a nested structure
Fields
A field object describes field requirements for create and detail views.
"schema": [
{
"alias": "<string>",
"type": "<type>",
"required": "<bool>"
}
]Each field, regardless of type, is represented by a JSON object with the following attributes:
alias– field aliastype– field typerequired– boolean flag indicating whether the field is required
Optionally, the following attributes may also be used:
validators– list of validators used to check whether the value is valid
"validators": ["<json>", "<json>"]Each validator has at least a type attribute and may include additional attributes depending on its type.
{
"type": "<string>"
}Supported validators:
| Type | Options | Description |
|---|---|---|
| min_length | minimal number of characters | Validates minimum string length |
| max_length | maximum number of characters | Validates maximum string length |
| min_value | minimal allowed value | Validates minimum numeric value |
| max_value | maximum allowed value | Validates maximum numeric value |
| date_in_future | Validates that a date is in the future |
Additionally, fields of type enum and set may have:
values– list of JSON objects with predefined values for the fieldautocomplete– relative URL to an API endpoint where available values can be obtained
Example:
"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
"schema": [
{
"alias": "<string>",
"schema": ["<json>"]
}
]A nested schema aggregates multiple fields into a nested JSON object. It always contains at least:
alias– alias of the groupschema– list of fields or another nested schema
Optionally, it may also contain:
schema_by_<alias>– used when the schema depends on the value of another fieldvalidators– list of validators that apply to the entire group of fields
Schema by value from a different field
schema_by_<alias> means that the schema depends on the value of another field.
At least two attributes are required:
alias– field whose value affects the schemaschema– list of fields in the schema
Example:
{
"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"
}
]
}
]
}
]
}
]
}Related validators
If a validator applies only to some fields in the group, an apply_to attribute is used to specify which fields are affected.
Supported validators:
| Type | Options | Description |
|---|---|---|
| max_length | maximal number of items in the group | Validates the maximum number of items allowed |
Example:
{
"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 the above example:
- only 1 reminder of
notice_type="task_complete_by"is allowed - a maximum of 10 reminders of
notice_type="task_overdue"are allowed
restrictions attribute
Contains any restrictions enforced for a particular endpoint.
Autocomplete
Some related API endpoints use data stored as an enum or set type.
In these cases, the OPTIONS request may include an autocomplete relative URL such as:
/api/users/autocomplete/Only GET requests are available on these endpoints.
Restrictions based on limits
When an endpoint is limited by the number of objects that can be created, the response should be:
HTTP 403 Forbiddenwith the following response body:
{
"detail": "Limit of {limit} {object_name} has been exceeded.",
"error_code": "ERR_LIMIT_EXCEEDED"
}