{
  "components": {
    "schemas": {
      "ListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "metadata": {
                "type": "object",
                "description": "Contains meta information about the result of the call",
                "properties": {
                  "total": {
                    "type": "integer",
                    "description": "Total number of records for call",
                    "example": 100
                  },
                  "actual": {
                    "type": "integer",
                    "description": "Number of records in the data array. This can be modified by passing a different \"limit\" query parameter.",
                    "example": 20
                  },
                  "editable": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "List of record IDs in the result, that are editable",
                    "example": [
                      1,
                      2,
                      3
                    ]
                  },
                  "deletable": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "List of record IDs in the result, that are deletable",
                    "example": [
                      4,
                      5,
                      6
                    ]
                  },
                  "deleted": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "List of record IDs in the result, that are deleted (currently in the RecycleBin)",
                    "example": [
                      4,
                      5,
                      6
                    ]
                  }
                }
              },
              "data": {
                "type": "array",
                "description": "Each record will in addition to the ID contain all requested fields. Check query parameter \"fields\" to change selection.<br>\nField specific features:<br>\n  * Reference: Will be an object with ID and name properties to avoid querying for data. In addition you get the entity name and if the record is visible by the current user.\n  * UsersGroupsReference: See Reference\n  * Date: Value will be formatted in ISO8601 format\n  * File: This field will not be returned in list response due to performance\n",
                "items": {
                  "properties": {
                    "id": {
                      "type": "integer",
                      "description": "The ID of the record",
                      "example": 1
                    },
                    "someField": {
                      "type": "string",
                      "example": "someValue"
                    },
                    "anotherField": {
                      "type": "integer",
                      "example": 1
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "DetailResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "metadata": {
                "type": "object",
                "description": "Contains meta information about the result of the call",
                "properties": {
                  "editable": {
                    "type": "boolean",
                    "description": "Determines if the record is editable by current user",
                    "example": true
                  },
                  "deletable": {
                    "type": "boolean",
                    "description": "Determines if the record is deletable by current user",
                    "example": false
                  },
                  "deleted": {
                    "type": "boolean",
                    "description": "Determines if the record is currently in the RecycleBin",
                    "example": false
                  }
                }
              },
              "data": {
                "type": "object",
                "description": "Contains all the fields described in the metadata endpoint for a single entity.<br>\nField specific features:<br>\n  * Reference: Will be an object with ID and name properties to avoid querying for data. In addition you get the entity name, a record number and if the record is visible by the current user.\n  * UsersGroupsReference: See Reference\n  * Date: Value will be formatted in ISO8601 format\n  * File: Will be an object with \"name\" and \"content\" properties. Currently only Documents entity has such a field.\n",
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "The ID of the record",
                    "example": 1
                  },
                  "someField": {
                    "type": "string",
                    "example": "someValue"
                  },
                  "anotherField": {
                    "type": "integer",
                    "example": 1
                  },
                  "someFile": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "The original file name"
                      },
                      "content": {
                        "type": "string",
                        "description": "Base64 encoded file content"
                      }
                    }
                  },
                  "lineItems": {
                    "type": "array",
                    "description": "This array will be included as one of the fields for inventory entities. It contains details about line items for this record.",
                    "items": {
                      "properties": {
                        "entityId": {
                          "type": "integer",
                          "description": "ID of the product or service for this item",
                          "example": 1
                        },
                        "lineItemId": {
                          "type": "integer",
                          "description": "The ID of the line item. If this is not set for edit, the item is assumed to be added.",
                          "example": 2
                        },
                        "lineItemType": {
                          "type": "string",
                          "description": "Describes the type of the entityId (Products or Services)",
                          "example": "Products"
                        },
                        "productName": {
                          "type": "string",
                          "description": "Name of the item",
                          "example": "Some product"
                        },
                        "listPrice": {
                          "type": "number",
                          "format": "double",
                          "description": "Price for a single item of this position. This value can have 3 decimal digits.<br>\n**For gross items this will be the calculated net price.**<br>\nWe use high precision decimal column for this internally but double is the only thing that can be documented here.\n",
                          "example": 223.95
                        },
                        "grossListPrice": {
                          "type": "number",
                          "format": "double",
                          "description": "Gross price for a single item of this position. This value can have 3 decimal digits.<br>\n**This value is only provided for gross items and must be used as listPrice when editing this record!**<br>\nWe use high precision decimal column for this internally but double is the only thing that can be documented here.\n",
                          "example": 223.95
                        },
                        "quantity": {
                          "type": "number",
                          "format": "float",
                          "description": "Quantity for this position. This value can have 3 decimal digits.",
                          "example": 25.552
                        },
                        "totalPrice": {
                          "type": "number",
                          "format": "double",
                          "description": "This equals listPrice times quantity. Only for displaying, this can not be modified by editing this record. It will be automatically calculated.",
                          "example": 22342
                        },
                        "afterDiscountPrice": {
                          "type": "number",
                          "format": "double",
                          "description": "Net price after applying discount but before adding taxes. Only for displaying, this can not be modified by editing this record. It will be automatically calculated.",
                          "example": 2000
                        },
                        "taxPercent": {
                          "type": "number",
                          "format": "float",
                          "description": "Because tax percentage is revision safe it will be returned in this result for display purposes.<br>\n**To be able to determine the correct percentage while editing a record, make sure lineItemId is set correctly for existing line items.**\n"
                        },
                        "taxValue": {
                          "type": "number",
                          "format": "double",
                          "description": "Amount of tax for this item. For group taxes this will be 0.<br>\nOnly for displaying, this can not be modified by editing this record. It will be automatically calculated.<br>\n",
                          "example": 125
                        },
                        "netPrice": {
                          "type": "number",
                          "format": "double",
                          "description": "Net price of the item after everything was applied. In case of individual tax type net = gross value. In case of group taxes, this value will not include taxes.<br>\nOnly for displaying, this can not be modified by editing this record. It will be automatically calculated.\n",
                          "example": 2323
                        },
                        "comment": {
                          "type": "string",
                          "description": "Additional description of an item",
                          "example": "This is a product for various purposes."
                        },
                        "grossItem": {
                          "type": "boolean",
                          "description": "If true, this position is treated as a gross item. In this case \"listPrice\" is assumed to be gross price. Also \"discountAmount\" is assumed to be a gross value.\n",
                          "example": false
                        },
                        "discountPercent": {
                          "type": "number",
                          "format": "float",
                          "description": "Percent discount for this item. Only discountPercent or discountAmount can be set at a time for one item. If both are given, discountPercent will be preferred.",
                          "example": 5
                        },
                        "discountAmount": {
                          "type": "number",
                          "format": "double",
                          "description": "Absolute discount for this item. If grossItem is true, this is the calculated net value.<br>\nOnly discountPercent or discountAmount can be set at a time for one item. If both are given, discountPercent will be preferred.\n",
                          "example": 81
                        },
                        "discountGrossAmount": {
                          "type": "number",
                          "format": "double",
                          "description": "Only for gross items. This is the specified absolute discount. This must be used for editing this line item.",
                          "example": 100
                        },
                        "totalWeightPosition": {
                          "type": "number",
                          "format": "double",
                          "description": "Represents the weight of a single item * quantity",
                          "example": 100
                        },
                        "surcharge": {
                          "type": "number",
                          "format": "float",
                          "description": "Percent of surcharge for this item. On edit this will be base for calculation.",
                          "example": 5
                        },
                        "surchargeTotal": {
                          "type": "number",
                          "format": "float",
                          "description": "The amount of surcharge for this item. Ignored on edit, will be calculated from surcharge.",
                          "example": 100
                        },
                        "taxClass": {
                          "type": "integer",
                          "description": "ID of the taxclass to use for this position. 0 = no tax class should be used which is also the default.",
                          "example": 412
                        },
                        "optionalLineItem": {
                          "type": "boolean",
                          "description": "If true line item is optional. <br> Works only for the modules Potentials (Deals).",
                          "example": false
                        },
                        "alternativeLineItem": {
                          "type": "boolean",
                          "description": "If true line item is alternative. <br> Works only for the modules Potentials (Deals).",
                          "example": false
                        },
                        "alternativeParentId": {
                          "type": "integer",
                          "description": "This number is the lineitemId of the parent lineitem (if the parent does not exist use alternativeParentIdentifier) if set this lineitem is going to be an alternative lineitem. If the value is 0 the alternative lineitem gets changed to an normal lineitem."
                        },
                        "cf_*": {
                          "type": "depends",
                          "description": "Change the key with the name of the customfield name (cf_1725).",
                          "example": "custom field value"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "CreatedResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CreatedResponse"
          },
          {
            "type": "object",
            "properties": {
              "metadata": {
                "type": "object",
                "description": "Contains meta information about the result of the call",
                "properties": {
                  "editable": {
                    "type": "boolean",
                    "description": "Determines if the record is editable by current user",
                    "example": true
                  },
                  "deletable": {
                    "type": "boolean",
                    "description": "Determines if the record is deletable by current user",
                    "example": false
                  }
                }
              },
              "data": {
                "type": "object",
                "description": "Contains all the fields described in the metadata endpoint for a single entity.<br>\nField specific features:<br>\n  * Reference: Will be an object with ID and name properties to avoid querying for data\n  * UsersGroupsReference: See Reference\n  * Date: Value will be formatted in ISO8601 format\n  * File: Must be an object with \"name\" and base64 encoded file \"content\". Currently only Documents entity has such a field.\n",
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "The ID of the record",
                    "example": 1
                  },
                  "firstField": {
                    "type": "string",
                    "description": "A field of the entity"
                  },
                  "secondField": {
                    "type": "integer",
                    "description": "Another field of the entity"
                  },
                  "someFile": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "The original name of the file"
                      },
                      "content": {
                        "type": "string",
                        "description": "Base64 encoded content of a file"
                      }
                    }
                  }
                }
              }
            }
          }
        ],
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Status code of the repsonse",
            "example": 201
          },
          "message": {
            "type": "string",
            "description": "Message of the response",
            "example": "Created"
          }
        }
      },
      "EditedResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "metadata": {
                "type": "object",
                "description": "Contains meta information about the result of the call",
                "properties": {
                  "editable": {
                    "type": "boolean",
                    "description": "Determines if the record is editable by current user",
                    "example": true
                  },
                  "deletable": {
                    "type": "boolean",
                    "description": "Determines if the record is deletable by current user",
                    "example": false
                  }
                }
              },
              "data": {
                "type": "object",
                "description": "Contains all the fields described in the metadata endpoint for a single entity.<br>\nField specific features:<br>\n  * Reference: Will be an object with ID and name properties to avoid querying for data\n  * UsersGroupsReference: See Reference\n  * Date: Value will be formatted in ISO8601 format\n  * File: Must be an object with \"name\" and base64 encoded file \"content\". Currently only Documents entity has such a field. Old file will be replaced.\n",
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "The ID of the record",
                    "example": 1
                  },
                  "firstField": {
                    "type": "string",
                    "description": "A field of the entity"
                  },
                  "secondField": {
                    "type": "integer",
                    "description": "Another field of the entity"
                  },
                  "someFile": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "The original name of the file"
                      },
                      "content": {
                        "type": "string",
                        "description": "Base64 encoded content of a file"
                      }
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "ChangesResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "description": "List of field names and their last changed date according to change tracking entries",
                "properties": {
                  "fieldName1": {
                    "type": "object",
                    "description": "Details of field with name \"fieldName1\"",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "The ID of the field",
                        "example": 1
                      },
                      "lastChanged": {
                        "type": "string",
                        "description": "ISO8601 date of last change for this field",
                        "example": "2025-02-18T12:38:48+00:00"
                      }
                    }
                  },
                  "fieldName2": {
                    "type": "object",
                    "description": "Details of field with name \"fieldName2\"",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "The ID of the field",
                        "example": 1
                      },
                      "lastChanged": {
                        "type": "string",
                        "description": "ISO8601 date of last change for this field",
                        "example": "2025-02-18T12:38:48+00:00"
                      }
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "TokenResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "description": "Object containing the tokens",
                "properties": {
                  "accessToken": {
                    "type": "string",
                    "description": "The JWT access token to use on every request in the Authorization header. Valid for 15 minutes.",
                    "example": "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSm9obiBEb2UifQ.K1lVDx..."
                  },
                  "refreshToken": {
                    "type": "string",
                    "description": "The refresh token to refresh the access token if it is expired. Valid for 7 days.",
                    "example": "c7701a80c1eda9761484f0d64f458d7bc2..."
                  }
                }
              }
            }
          }
        ]
      },
      "ChallengeResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "description": "Object containing the challenge token",
                "properties": {
                  "challengeToken": {
                    "type": "string",
                    "description": "A challenge token to use in the /code route, valid for 60 seconds",
                    "example": "c7701a80c1eda9761484f0d64f458d7bc2..."
                  }
                }
              }
            }
          }
        ]
      },
      "EntityResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "properties": {
                    "id": {
                      "type": "integer",
                      "description": "The ID of the entity"
                    },
                    "name": {
                      "type": "string",
                      "description": "Internal name of the entity. You should not use it for displaying to the user, only for identifying it internally."
                    },
                    "icon": {
                      "type": "string",
                      "description": "This is the name of the FontAwesome icon used for this entity inside the CRM"
                    },
                    "isEntity": {
                      "type": "boolean",
                      "description": "Determines if this is a real or a helper entity"
                    },
                    "isInventory": {
                      "type": "boolean",
                      "description": "Determines if this entity has line items (in case of Deals they are optional)"
                    },
                    "create": {
                      "type": "boolean",
                      "description": "Does the user have permission to create new records for this entity"
                    },
                    "update": {
                      "type": "boolean",
                      "description": "Does the user have permission to update records for this entity"
                    },
                    "delete": {
                      "type": "boolean",
                      "description": "Does the user have permission to delete records for this entity"
                    },
                    "readonly": {
                      "type": "boolean",
                      "description": "If this is true, records can only be retrieved but not modified or deleted over the API"
                    },
                    "label": {
                      "type": "string",
                      "description": "Module name translated to the language of the user. This should be used to display the entity to the user. There will be no translation for helper entities, instead the name is used here."
                    },
                    "singular": {
                      "type": "string",
                      "description": "Singular translation of the module name in the language of the user. This does not exist for helper entities."
                    },
                    "views": {
                      "type": "array",
                      "description": "Available views for the module. Helper entities don't have views.",
                      "items": {
                        "properties": {
                          "id": {
                            "type": "integer",
                            "description": "ID of the view"
                          },
                          "name": {
                            "type": "string",
                            "description": "Display name of the view"
                          },
                          "default": {
                            "type": "boolean",
                            "description": "Determines the default view of the user"
                          }
                        }
                      }
                    },
                    "nameFields": {
                      "type": "array",
                      "description": "A list of fields that represent the title fields of the module, usually one but in rare cases e.g. Contacts there are two firstname and lastname.",
                      "items": {
                        "type": "string",
                        "example": "accountname"
                      }
                    }
                  }
                },
                "example": [
                  {
                    "id": 23,
                    "name": "Invoice",
                    "icon": "faCredit",
                    "isEntity": true,
                    "create": true,
                    "update": true,
                    "delete": false,
                    "readonly": false,
                    "label": "Invoices",
                    "singular": "Invoice",
                    "views": [
                      {
                        "id": 0,
                        "name": "Standard",
                        "default": true
                      },
                      {
                        "id": 25,
                        "name": "Standard [copy]",
                        "default": false
                      }
                    ],
                    "nameFields": [
                      "title"
                    ]
                  },
                  {
                    "id": 73,
                    "name": "Currencies",
                    "isEntity": false,
                    "create": false,
                    "update": false,
                    "delete": false,
                    "readonly": true,
                    "label": "Currencies",
                    "singular": "",
                    "views": [],
                    "nameFields": [
                      "currency_name"
                    ]
                  }
                ]
              }
            }
          }
        ]
      },
      "FieldResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "fields": {
                    "type": "array",
                    "items": {
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Name of the field which must be used to access data of results or to save values of records to create/edit",
                          "example": "DemoField"
                        },
                        "label": {
                          "type": "string",
                          "description": "Label of the field translated to user language which should be used to display the field to the user",
                          "example": "Demo Field"
                        },
                        "length": {
                          "type": "integer",
                          "description": "Length of the field. Not all fields need spedicif length which is expressed by the value 0.",
                          "example": 100
                        },
                        "type": {
                          "type": "string",
                          "description": "Type of the field",
                          "enum": [
                            "Checkbox",
                            "Currency",
                            "DateTime",
                            "Email",
                            "File",
                            "Image",
                            "LanguagePickList",
                            "ModuleFieldType",
                            "MultiPickList",
                            "Number",
                            "Password",
                            "Percentage",
                            "Phone",
                            "PickList",
                            "Reference",
                            "RoleReference",
                            "Skype",
                            "StateCode",
                            "TaxClass",
                            "Text",
                            "Textarea",
                            "Url",
                            "UsersGroupsReference"
                          ],
                          "example": "Text"
                        },
                        "block": {
                          "type": "integer",
                          "description": "ID of the block (also see blocks property of result to match ID to label)",
                          "example": 4
                        },
                        "required": {
                          "type": "boolean",
                          "description": "If true, this field is required for creating or editing a record",
                          "example": false
                        },
                        "editable": {
                          "type": "boolean",
                          "description": "If true, this field can be set on create/edit of a record",
                          "example": true
                        },
                        "refEntities": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "description": "Internal module name of modules that can be referenced by this field. Only provided for fields of type Reference.",
                            "example": "Accounts"
                          }
                        },
                        "values": {
                          "type": "array",
                          "description": "Provides possible values of a field. If a pick list doesn't provide values, you may have to retrieve values of a helper entity, e.g. InventoryTax or Currencies.<br>\nFields of type StateCode only provide values when the request carries the \"country\" query parameter — without it their values list is empty, because the full ISO 3166-2 list holds thousands of entries.\n",
                          "items": {
                            "type": "object",
                            "properties": {
                              "value": {
                                "oneOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "integer"
                                  }
                                ],
                                "description": "This represents the value in records and also the value to use to save records on create/edit.",
                                "example": "Mr"
                              },
                              "label": {
                                "type": "string",
                                "description": "The translated label to show to the user, usually in select boxes",
                                "example": "Mister"
                              },
                              "color": {
                                "type": "object",
                                "description": "(Optional) only exists if a color is defined for at least one of the field values through field configuration in module management -> layout settings",
                                "properties": {
                                  "background": {
                                    "type": "string",
                                    "description": "Hex color used as background",
                                    "example": "#FFEBE5"
                                  },
                                  "text": {
                                    "type": "string",
                                    "description": "Hex color used for text",
                                    "example": "#FF3C00"
                                  }
                                }
                              }
                            }
                          }
                        },
                        "format": {
                          "type": "string",
                          "description": "Some field types (like date) provide information on how they should be formatted when presented to the user to respect their settings.<br>\nDates are always formatted using ISO8601 no matter how they should be presented.\n",
                          "example": ""
                        },
                        "richText": {
                          "type": "boolean",
                          "description": "Only available for type \"Textarea\". If true, this field can contain HTML code.",
                          "example": false
                        }
                      }
                    }
                  },
                  "blocks": {
                    "type": "array",
                    "items": {
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "ID of the block which is included in the fields array as well and can be used to map blocks to fields",
                          "example": 4
                        },
                        "label": {
                          "type": "string",
                          "description": "Label of the block translated to user language which should be used to show blocks to user if needed",
                          "example": "Contact Information"
                        }
                      }
                    }
                  },
                  "userDefinedFields": {
                    "type": "array",
                    "description": "Describes the user defined fields for line items of inventory modules",
                    "items": {
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Fieldname of the userdefined field.",
                          "example": "cf_1725"
                        },
                        "label": {
                          "type": "string",
                          "description": "The translated field name.",
                          "example": "field name"
                        },
                        "length": {
                          "type": "integer",
                          "description": "Max length of field.",
                          "example": 100
                        },
                        "type": {
                          "type": "string",
                          "description": "Type of the field.",
                          "example": "Text"
                        },
                        "block": {
                          "type": "integer",
                          "description": "Block id of the field.",
                          "example": 70
                        },
                        "required": {
                          "type": "boolean",
                          "description": "Is the field mandatory?",
                          "example": false
                        },
                        "editable": {
                          "type": "boolean",
                          "description": "Is the field editable?",
                          "example": false
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "SuccessResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Status code of the repsonse",
            "example": 200
          },
          "message": {
            "type": "string",
            "description": "Message of the response",
            "example": "OK"
          }
        }
      },
      "UserResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "description": "**Contains a limited amount of the fields** described in the metadata endpoint for the Users entity.<br>\nField specific features:<br>\n  * Reference: Will be an object with ID and name properties to avoid querying for data\n  * UsersGroupsReference: See Reference\n  * Date: Value will be formatted in ISO8601 format\n  * Image: Will be an object with \"name\" and \"content\" properties. For example the user image.\n",
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "The ID of the user",
                    "example": 1
                  },
                  "someField": {
                    "type": "string",
                    "example": "someValue"
                  },
                  "anotherField": {
                    "type": "integer",
                    "example": 1
                  },
                  "imagename": {
                    "type": "object",
                    "description": "The image of the user",
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "The original file name"
                      },
                      "content": {
                        "type": "string",
                        "description": "Base64 encoded file content"
                      }
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "CompaniesResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SuccessResponse"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "description": "List of companies the user has access to",
                "items": {
                  "properties": {
                    "id": {
                      "type": "integer",
                      "description": "The ID of the company",
                      "example": 1
                    },
                    "name": {
                      "type": "string",
                      "description": "The name of the company",
                      "example": "Your Company Ltd."
                    }
                  }
                }
              }
            }
          }
        ]
      }
    },
    "responses": {
      "BadRequestError": {
        "description": "Bad Request. Check message for specific information about the error of the request.",
        "content": {
          "application/vnd.brainformatik.crm-v1+json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "description": "The status code of the error",
                  "example": 400
                },
                "message": {
                  "type": "string",
                  "description": "Message of the error",
                  "example": "This is not a valid date."
                }
              }
            }
          }
        }
      },
      "UnauthorizedError": {
        "description": "Unauthorized. Usually means something is wrong with credentials or token.",
        "content": {
          "application/vnd.brainformatik.crm-v1+json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "description": "The status code of the error",
                  "example": 401
                },
                "message": {
                  "type": "string",
                  "description": "Message of the error",
                  "example": "Unauthorized."
                }
              }
            }
          }
        }
      },
      "ForbiddenError": {
        "description": "Forbidden. Usually means user does not have access to the requested resource.",
        "content": {
          "application/vnd.brainformatik.crm-v1+json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "description": "The status code of the error",
                  "example": 403
                },
                "message": {
                  "type": "string",
                  "description": "Message of the error",
                  "example": "Forbidden."
                }
              }
            }
          }
        }
      },
      "NotFoundError": {
        "description": "Not found. Usually means the requested resource does not exist.",
        "content": {
          "application/vnd.brainformatik.crm-v1+json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "description": "The status code of the error",
                  "example": 404
                },
                "message": {
                  "type": "string",
                  "description": "Message of the error",
                  "example": "Not found."
                }
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Too many requests. Call exceeds the rate limit.",
        "content": {
          "application/vnd.brainformatik.crm-v1+json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "description": "The status code of the error",
                  "example": 429
                },
                "message": {
                  "type": "string",
                  "description": "Message of the error",
                  "example": "Too many requests"
                }
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Internal server errror. You should contact the service provider.",
        "content": {
          "application/vnd.brainformatik.crm-v1+json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "description": "The status code of the error",
                  "example": 500
                },
                "message": {
                  "type": "string",
                  "description": "Message of the error",
                  "example": "Internal server error."
                }
              }
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Service is currently unavailable. Usually returned during maintanance.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "description": "The status code of the error",
                  "example": 503
                },
                "message": {
                  "type": "string",
                  "description": "Message of the error",
                  "example": "Service Unavailable"
                }
              }
            }
          }
        }
      },
      "NotImplementedError": {
        "description": "The called operation is currently not supported",
        "content": {
          "application/vnd.brainformatik.crm-v1+json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "description": "The status code of the error",
                  "example": 501
                },
                "message": {
                  "type": "string",
                  "description": "Message of the error. Usually very specific.",
                  "example": "This operation is not supported for this entity"
                }
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "paths": {
    "/entity/{entityId}/records": {
      "get": {
        "summary": "Retrieve records for an entity",
        "description": "Use this action to get a list of records for an entity. Have a look at query parameters for details on how to modify the result.",
        "parameters": [
          {
            "in": "path",
            "name": "entityId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the entity",
            "example": 6
          },
          {
            "in": "query",
            "name": "offset",
            "schema": {
              "type": "integer"
            },
            "description": "The number of records to skip before starting the list. This can be used for pagination."
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer"
            },
            "description": "The number of records to retrieve, if nothing is provided, the default value for lists inside the CRM will be used. There is a hard maximum of 200 records.",
            "example": 20
          },
          {
            "in": "query",
            "name": "fields",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "style": "pipeDelimited",
            "explode": false,
            "example": [
              "accountname",
              "industry",
              "assigned_user_id"
            ],
            "description": "The fields you want to retrieve separated by a pipe \"|\". If no special selection is provided, the fields from \"All\" list view in the CRM is returned. You can use * to retrieve all fields (may be slow)."
          },
          {
            "in": "query",
            "name": "includeDeleted",
            "schema": {
              "type": "boolean"
            },
            "description": "If true, query will also include deleted records (the ones that are in the RecycleBin, records no longer in the system cannot be fetched)",
            "example": true
          },
          {
            "in": "query",
            "name": "includeFileContent",
            "schema": {
              "type": "boolean"
            },
            "description": "If true, content of file fields will be included. This might be very slow depending on the file sizes and limit parameter!",
            "example": true
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "type": "object",
              "properties": {
                "fieldName": {
                  "type": "string"
                }
              }
            },
            "style": "deepObject",
            "explode": true,
            "description": "Sort by specific field in specified order. You can add as many fields as you want.<br> Format in URL is **order[fieldName]=ASC&order[otherField]=DESC**<br>",
            "example": {
              "fieldName": "ASC"
            }
          },
          {
            "in": "query",
            "name": "filter",
            "schema": {
              "type": "object",
              "properties": {
                "fieldName": {
                  "type": "string"
                }
              }
            },
            "style": "deepObject",
            "explode": true,
            "description": "- You can separate multiple values by pipe \"|\". They will be combined with OR.<br>\n- Format in URL is **filter[fieldName]=someValue|someOtherValue**<br>\n- It is possible to filter records by their ID: **filter[id]=123|456|789**\n- There is also a universal filter for record names, so no need to get main field of a module: **filter[recordName]=Name1|Name2**\n- Filter values must be raw values which means the same format as you receive it, except for type \"Reference\" where you can use text instead of object or ids.<br>\n- If the value (right side of the = sign) starts with a \"!\" this means \"not equals\". In this case values separated with pipe will be combined with AND.<br>\n- You can also use > and < signs as first character of the filter value to search for values greater or less than the value: filter[fieldName]=>someValue|<someOtherValue<br>\n- Usually filter for text uses a \"LIKE\" search which means a filter is true if part of the text matches. \n  You can use an additional equal sign in front of the value to change to exact matches (**filter[fieldName]==someExactValue**). \n  This can be combined with the not operator (**filter[fieldName]=!=notSomeExactValue**)<br>\n- If reference field compare value is numeric, ID is assumed and will be used instead of name of a record\n  - Reference fields can also be filtered by record number instead of IDs\n- If you filter by date fields that contain time the \"equals\" and \"not equals\" comparators ignore the seconds\n- In case of phone numbers, you can enable a comparison with a regex filter that keeps the digits and their order, but ignores all other characters\n  - This can be activated by using the \"exact filter\" function with == described above\n  - To match this filter, you must provide all digits of the phone number, it is not possible to only search for area code for example\n  - Note that things like +49... or 0049... will not be converted automatically for this\n- If you need a field more than once, you can provide an array by appending [] at the end:<br> **filter[fieldName][]=someValue&filter[fieldName][]=someOtherValue**<br>\n  Make sure that every filter for this field has the [] brackets at the end, otherwise it will be overwritten incorrectly\n",
            "example": {
              "fieldName": "someValue"
            }
          },
          {
            "in": "query",
            "name": "filter0",
            "schema": {
              "type": "object",
              "properties": {
                "fieldName": {
                  "type": "string"
                }
              }
            },
            "style": "deepObject",
            "explode": true,
            "description": "For more complex filter, it is possible to use several filter names where a numeric value will determine the filter group.<br>\nFields inside a filter group will always be combined with AND. You can combine the groups with OR using **filterOr** query parameter (see next parameter).<br>\nFormat in URL **filter0[firstname]=John&filter0[lastname]=Doe**\n",
            "example": {
              "fieldName": "someValue"
            }
          },
          {
            "in": "query",
            "name": "filterOr",
            "schema": {
              "type": "boolean"
            },
            "description": "If this is true, then given filter fields (or groups) will be combined with OR instead of AND.<br>\nIf at least two groups exist, this will affect only the combination of groups, not the fields inside each group.\n"
          }
        ],
        "tags": [
          "Records"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplementedError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "summary": "Create a new record for an entity",
        "description": "Use this action to create a new record for an entity.",
        "parameters": [
          {
            "in": "path",
            "name": "entityId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the entity",
            "example": 6
          }
        ],
        "requestBody": {
          "description": "Data of the record to create. If the object contains fields or values that are not allowed for current user, an error will be thrown.<br>\nAll required fields must be provided or an error is thrown as well.<br>\nThe record is validated with the same rules as the edit view of the CRM (conditional mandatory fields, date dependencies, uniqueness, entity specific rules).\nIf a rule fails, status 400 is returned with a \"Validation failed\" message that lists each field and the reason.<br>\nValues should be provided in the same format, as it would be retrieved except for the following special cases.<br>\nField specific features:<br>\n  * Reference: Must be the ID of the record\n  * UsersGroupsReference: See Reference. The assigned_user_id can also be a group retrieved through the Groups helper entity. All other UsersGroupsReference fields can only contain users.\n  * Record number field will be auto-generated.\n",
          "required": true,
          "content": {
            "application/vnd.brainformatik.crm-v1+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "firstField": {
                    "type": "string",
                    "description": "A field of the entity"
                  },
                  "secondField": {
                    "type": "integer",
                    "description": "Another field of the entity"
                  },
                  "lineItems": {
                    "type": "array",
                    "description": "This property must be set for inventory modules (except for Deals, where line items are optional). <br> <b>WARNING lineItems must be added in the right order otherwise the behavior is undefined.</b>",
                    "items": {
                      "type": "object",
                      "properties": {
                        "entityId": {
                          "type": "integer",
                          "description": "ID of the product or service for this item",
                          "example": 1
                        },
                        "productName": {
                          "type": "string",
                          "description": "Name of the item, can differ from product/service name",
                          "example": "Some product"
                        },
                        "listPrice": {
                          "type": "number",
                          "format": "double",
                          "description": "Price for a single item of this position. You can use 3 decimal digits for this value.<br>\nWe use high precision decimal column for this internally but double is the only thing that can be documented here.\n",
                          "example": 223.95
                        },
                        "quantity": {
                          "type": "number",
                          "format": "float",
                          "description": "Quantity for this position. You can use 3 decimal digits for this value.",
                          "example": 25.552
                        },
                        "comment": {
                          "type": "string",
                          "description": "Additional description of an item",
                          "example": "This is a product for various purposes."
                        },
                        "grossItem": {
                          "type": "boolean",
                          "description": "If true, this position is treated as a gross item. In this case \"listPrice\" is assumed to be gross price. Also \"discountAmount\" is assumed to be a gross value.<br>\nFor consistency this should always match the corresponding flag of the item product or service specified with \"entityId\".\n",
                          "example": false
                        },
                        "discountPercent": {
                          "type": "number",
                          "format": "float",
                          "description": "Percent discount for this item. Only discountPercent or discountAmount can be set at a time for one item. If both are given, discountPercent will be preferred.",
                          "example": 5
                        },
                        "discountAmount": {
                          "type": "number",
                          "format": "double",
                          "description": "Absolute discount for this item. If grossItem is true, this must be the gross value.<br>\nOnly discountPercent or discountAmount can be set at a time for one item. If both are given, discountPercent will be preferred.\n",
                          "example": 100
                        },
                        "taxClass": {
                          "type": "integer",
                          "description": "ID of the taxclass to use for this position. 0 = no tax class should be used which is also the default.",
                          "example": 412
                        },
                        "productBlockName": {
                          "type": "string",
                          "description": "If set an product block gets set, else the default block gets picked. <br> Values are \"ArticleList1\" for the default block or \"article_list_1\" for example the 1 can be replaced with any number depending on how many product blocks the CRM has.",
                          "example": "article_list_2"
                        },
                        "optionalLineItem": {
                          "type": "boolean",
                          "description": "If true line item is optional. <br> Works only for the modules Potentials (Deals).",
                          "example": false
                        },
                        "alternativeLineItem": {
                          "type": "boolean",
                          "description": "If true line item is alternative. <br> Works only for the modules Potentials (Deals).",
                          "example": false
                        },
                        "alternativeParentNumber": {
                          "type": "integer",
                          "description": "This number is an identifier for the parent of alternative lineitems. Every lineitem with alternativeParentIdentifier set to this number is going to be an alternative lineitem child of this lineitem."
                        },
                        "alternativeParentIdentifier": {
                          "type": "integer",
                          "description": "This number is used for all childs of the alternativeParentNumber it has to be the same number like alternativeParentNumber if its an alternative child of the lineitem."
                        },
                        "cf_*": {
                          "type": "depends",
                          "description": "Change the key with the name of the customfield name (cf_1725).",
                          "example": "custom field value"
                        }
                      },
                      "required": [
                        "entityId",
                        "productName",
                        "listPrice",
                        "quantity"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Records"
        ],
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplementedError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/entity/{entityId}/records/{recordId}": {
      "get": {
        "summary": "Retrieve a specific record of an entity",
        "description": "This will return all the data of a single record. Details about the data fields can be obtained by calling the corresponding metadata endpoint",
        "parameters": [
          {
            "in": "path",
            "name": "entityId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the entity",
            "example": 6
          },
          {
            "in": "path",
            "name": "recordId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the record"
          },
          {
            "in": "query",
            "name": "includeFileContent",
            "schema": {
              "type": "boolean"
            },
            "description": "If false, content of file fields will NOT be included. This might save some response time in case of larger files, if they are not (directly) needed!",
            "example": false
          }
        ],
        "tags": [
          "Records"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/DetailResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplementedError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "summary": "Edit an existing record",
        "description": "Use this action to edit an existing record of an entity.",
        "parameters": [
          {
            "in": "path",
            "name": "entityId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the entity",
            "example": 6
          },
          {
            "in": "path",
            "name": "recordId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the record"
          }
        ],
        "requestBody": {
          "description": "Data of the record to edit. If the object contains fields or values that are not allowed for current user, an error will be thrown.<br>\nIf required fields are in the object they must have a value or an error is thrown as well.<br>\nThe given fields are validated with the same rules as the edit view of the CRM (conditional mandatory fields, date dependencies, uniqueness, entity specific rules).\nDependencies are checked against the stored values of the record. If a rule fails, status 400 is returned with a \"Validation failed\" message that lists each field and the reason.<br>\nValues should be provided in the same format, as it would be retrieved except for the following special cases.<br>\nField specific features:<br>\n  * Reference: Must be the ID of the record\n  * UsersGroupsReference: See Reference. The assigned_user_id can also be a group retrieved through the Groups helper entity. All other UsersGroupsReference fields can only contain users.\n  * Record number field is not editable.\n",
          "required": true,
          "content": {
            "application/vnd.brainformatik.crm-v1+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "firstField": {
                    "type": "string",
                    "description": "A field of the entity"
                  },
                  "secondField": {
                    "type": "integer",
                    "description": "Another field of the entity"
                  },
                  "lineItems": {
                    "type": "array",
                    "description": "Optional for editing records. This property can be set for inventory modules.<br>\n**If it is set, it must contain all line items**. E.g. if only one item is given, all other items that might exist will be removed!\n<br> <b>WARNING lineItems must be added in the right order otherwise the behavior is undefined.</b>\n",
                    "items": {
                      "type": "object",
                      "properties": {
                        "entityId": {
                          "type": "integer",
                          "description": "ID of the product or service for this item",
                          "example": 1
                        },
                        "productName": {
                          "type": "string",
                          "description": "Name of the item, can differ from product/service name",
                          "example": "Some product"
                        },
                        "listPrice": {
                          "type": "number",
                          "format": "double",
                          "description": "Price for a single item of this position. You can use 3 decimal digits for this value.<br>\nWe use high precision decimal column for this internally but double is the only thing that can be documented here.\n",
                          "example": 223.95
                        },
                        "quantity": {
                          "type": "number",
                          "format": "float",
                          "description": "Quantity for this position. You can use 3 decimal digits for this value.",
                          "example": 25.552
                        },
                        "lineItemId": {
                          "type": "integer",
                          "description": "The ID of an existing line item. Will be provided if you retrieve a record through the GET action. If this is not set for edit, the item is assumed to be added.",
                          "example": 2
                        },
                        "comment": {
                          "type": "string",
                          "description": "Additional description of an item",
                          "example": "This is a product for various purposes."
                        },
                        "grossItem": {
                          "type": "boolean",
                          "description": "If true, this position is treated as a gross item. In this case \"listPrice\" is assumed to be gross price. Also \"discountAmount\" is assumed to be a gross value.<br>\nFor consistency this should always match the corresponding flag of the item product or service specified with \"entityId\".\n",
                          "example": false
                        },
                        "discountPercent": {
                          "type": "number",
                          "format": "float",
                          "description": "Percent discount for this item. Only discountPercent or discountAmount can be set at a time for one item. If both are given, discountPercent will be preferred.",
                          "example": 5
                        },
                        "discountAmount": {
                          "type": "number",
                          "format": "double",
                          "description": "Absolute discount for this item. If grossItem is true, this must be the gross value.<br>\nOnly discountPercent or discountAmount can be set at a time for one item. If both are given, discountPercent will be preferred.\n",
                          "example": 100
                        },
                        "taxClass": {
                          "type": "integer",
                          "description": "ID of the taxclass to use for this position. 0 = no tax class should be used which is also the default.",
                          "example": 412
                        },
                        "productBlockName": {
                          "type": "string",
                          "description": "If set an product block gets set, else the default block gets picked. <br> Values are \"ArticleList1\" for the default block or \"article_list_1\" for example the 1 can be replaced with any number depending on how many product blocks the CRM has.",
                          "example": "article_list_2"
                        },
                        "optionalLineItem": {
                          "type": "boolean",
                          "description": "If true line item is optional. <br> Works only for the modules Potentials (Deals).",
                          "example": false
                        },
                        "alternativeLineItem": {
                          "type": "boolean",
                          "description": "If true line item is alternative. <br> Works only for the modules Potentials (Deals).",
                          "example": false
                        },
                        "alternativeParentNumber": {
                          "type": "integer",
                          "description": "This number is an identifier for the parent of alternative lineitems. Every lineitem with alternativeParentIdentifier set to this number is going to be an alternative lineitem child of this lineitem."
                        },
                        "alternativeParentIdentifier": {
                          "type": "integer",
                          "description": "This number is used for all childs of the alternativeParentNumber it has to be the same number like alternativeParentNumber if its an alternative child of the lineitem."
                        },
                        "alternativeParentId": {
                          "type": "integer",
                          "description": "This number is the lineitemId of the parent lineitem (if the parent does not exist use alternativeParentIdentifier) if set this lineitem is going to be an alternative lineitem. If the value is 0 the alternative lineitem gets changed to an normal lineitem."
                        },
                        "cf_*": {
                          "type": "depends",
                          "description": "Change the key with the name of the customfield name (cf_1725).",
                          "example": "custom field value"
                        }
                      },
                      "required": [
                        "entityId",
                        "productName",
                        "listPrice",
                        "quantity"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Records"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/EditedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplementedError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "summary": "Delete a specific record of an entity",
        "description": "Mark a record as deleted. It can still be restored from recycle bin inside the CRM.",
        "parameters": [
          {
            "in": "path",
            "name": "entityId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the entity",
            "example": 6
          },
          {
            "in": "path",
            "name": "recordId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the record"
          }
        ],
        "tags": [
          "Records"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplementedError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/entity/{entityId}/records/{recordId}/changes": {
      "get": {
        "summary": "Get information about last field changes",
        "description": "This endpoint provides information about the latest changes of the record on a per field basis, based on change tracking entries.\nIf field was never changed, this corresponds to created time.\n",
        "tags": [
          "Records"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangesResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/auth": {
      "post": {
        "summary": "Login to service",
        "description": "All other services need a valid authentication, which you will get by calling this action. In case of 2-factor-authentication you can either use an apiPassword or implement the usual flow (only for TOTP, not WebAuthN)",
        "tags": [
          "Auth"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "setCookie",
            "schema": {
              "type": "integer"
            },
            "required": false,
            "description": "If set to \"1\" a httponly cookie is set for authentication and only the \"refreshToken\" is sent back"
          }
        ],
        "requestBody": {
          "description": "Data of the user to login",
          "required": true,
          "content": {
            "application/vnd.brainformatik.crm-v1+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user": {
                    "type": "string",
                    "description": "The user name to authenticate"
                  },
                  "password": {
                    "type": "string",
                    "description": "The password of the user to authenticate. If 2-factor-authentication is active, you can use an app password instead, which can be created in \"My settings\". If no apiPassword parameter is provided and TOTP is enabled, you will get a 201 response with a challenge token to use in the /code route to complete the 2-factor-login"
                  },
                  "apiPassword": {
                    "type": "string",
                    "description": "If 2-factor-authentication is active, use this instead of the password."
                  }
                },
                "required": [
                  "user"
                ]
              }
            },
            "application/vnd.brainformatik.crm-v2+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user": {
                    "type": "string",
                    "description": "The user name to authenticate"
                  },
                  "password": {
                    "type": "string",
                    "description": "The password of the user to authenticate. If 2-factor-authentication is active, you can use an app password instead, which can be created in \"My settings\". If no apiPassword parameter is provided and TOTP is enabled, you will get a 201 response with a challenge token to use in the /code route to complete the 2-factor-login"
                  },
                  "apiPassword": {
                    "type": "string",
                    "description": "If 2-factor-authentication is active, use this instead of the password. **The app password must be hashed with sha512 algorithm.**"
                  }
                },
                "required": [
                  "user"
                ]
              }
            }
          }
        },
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "201": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/ChallengeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "summary": "Logout of service",
        "tags": [
          "Auth"
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ]
      }
    },
    "/auth/refresh": {
      "post": {
        "summary": "Refresh an access token",
        "description": "This action will refresh an access token and also creates a new refresh token that you have to use to refresh the newly created access token",
        "tags": [
          "Auth"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "setCookie",
            "schema": {
              "type": "integer"
            },
            "required": false,
            "description": "If set to \"1\" a httponly cookie is set for authentication and only the \"refreshToken\" is sent back"
          }
        ],
        "requestBody": {
          "description": "Refresh token to use",
          "required": true,
          "content": {
            "application/vnd.brainformatik.crm-v1+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "refreshToken": {
                    "type": "string",
                    "description": "Refresh token",
                    "example": "c7701a80c1eda9761484f0d64f458d7bc2..."
                  }
                },
                "required": [
                  "refreshToken"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/auth/code": {
      "post": {
        "summary": "Provide 2-factor-code for a login challenge",
        "description": "This action will use the challenge token provided by login action and the 2-factor-code to complete a pending login challenge",
        "tags": [
          "Auth"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "setCookie",
            "schema": {
              "type": "integer"
            },
            "required": false,
            "description": "If set to \"1\" a httponly cookie is set for authentication and only the \"refreshToken\" is sent back"
          }
        ],
        "requestBody": {
          "description": "Data to complete login",
          "required": true,
          "content": {
            "application/vnd.brainformatik.crm-v1+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "challengeToken": {
                    "type": "string",
                    "description": "Challenge token retrieved by /login route, if user has 2FA with TOTP enabled",
                    "example": "c7701a80c1eda9761484f0d64f458d7bc2..."
                  },
                  "code": {
                    "type": "string",
                    "description": "2FA code provided by authenticator apps",
                    "example": 643345
                  }
                },
                "required": [
                  "challengeToken",
                  "code"
                ]
              }
            }
          }
        },
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/metadata/entities": {
      "get": {
        "summary": "Retrieve metadata about all entities",
        "description": "Contains detailed information about the entities like translation or permissions. Also lists helper entities that are required to create certain entity records, like Currencies for Invoices.",
        "tags": [
          "Metadata"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/EntityResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/metadata/entities/{entityId}": {
      "get": {
        "summary": "Retrieve metadata about a specific entity",
        "description": "Contains detailed information about blocks and fields of the module. Lists of blocks and fields are sorted as defined in the layout editor.",
        "parameters": [
          {
            "in": "path",
            "name": "entityId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the entity"
          },
          {
            "in": "query",
            "name": "country",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            },
            "description": "ISO 3166-1 alpha-2 country code (e.g. DE). If given, fields of type StateCode list the state codes of this country as their values. Without it, StateCode fields provide no values.",
            "example": "DE"
          }
        ],
        "tags": [
          "Metadata"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/metadata/entities/{entityId}/view/{viewId}": {
      "get": {
        "summary": "Retriev metadata about a specific entity with custom edit view",
        "description": "Contains detailed information about blocks and fields of the module and a specific view. Lists of blocks and fields are sorted as defined in the layout editor.",
        "parameters": [
          {
            "in": "path",
            "name": "entityId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the entity"
          },
          {
            "in": "path",
            "name": "viewId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the view. Existing views are listed in the result of /metadata/entities"
          },
          {
            "in": "query",
            "name": "country",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            },
            "description": "ISO 3166-1 alpha-2 country code (e.g. DE). If given, fields of type StateCode list the state codes of this country as their values. Without it, StateCode fields provide no values.",
            "example": "DE"
          }
        ],
        "tags": [
          "Metadata"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/relations/{recordId}": {
      "get": {
        "summary": "Retrieve relations of a record",
        "description": "Contains detailed information about records and their entities that have a relation to given record. Only records and entities that are visible by the user will be returned.<br>\nTo retrieve details about records, use the list method of the Records section. You can filter by \"id\" field.<br>\n**Note:** The URL for getting related records should not be longer than 2.000 characters, but this should not be a problem even with 200 records and IDs in the area of 1.000.000+.\n",
        "parameters": [
          {
            "in": "path",
            "name": "recordId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the record"
          }
        ],
        "tags": [
          "Relations"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "type": "array",
                  "description": "List of relational entites and their records.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "entityId": {
                        "type": "integer",
                        "description": "The entity ID of the related entity. Use this to get the list of related records with the corresponding action of the Records.",
                        "example": 4
                      },
                      "entityName": {
                        "type": "string",
                        "description": "The internal name of the entity.",
                        "example": "Contacts"
                      },
                      "label": {
                        "type": "string",
                        "description": "The translated label of the relation. Should be used to display it to the user.",
                        "example": "Contact List"
                      },
                      "count": {
                        "type": "integer",
                        "description": "The number of records related to that record.",
                        "example": 4
                      },
                      "idList": {
                        "type": "array",
                        "items": {
                          "type": "integer"
                        },
                        "description": "The list of IDs of the related records in the entity. Use this in combination with entityId and a filter on \"id\" field in the list action of the Records section of this documentation.",
                        "example": [
                          1,
                          2,
                          3,
                          4
                        ]
                      },
                      "add": {
                        "type": "boolean",
                        "description": "If true a new relation can be added by using POST action. Otherwise you have to create a new record manually because usually the relation is made by a field in the relational module.",
                        "example": true
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "summary": "Create a new relation for given record",
        "description": "Use this action to create a new relation between records. The user must have permission to see all records and the entity must support adding new relations (check \"add\" field of GET relations).\n",
        "parameters": [
          {
            "in": "path",
            "name": "recordId",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the record to add a relation for"
          }
        ],
        "requestBody": {
          "description": "Provide the list of records you want to add as relations to the given recrod",
          "required": true,
          "content": {
            "application/vnd.brainformatik.crm-v1+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "records": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "List of records to add as relation"
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Relations"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/users/current": {
      "get": {
        "summary": "Retrieve information about the current user",
        "description": "Use this action to get details about the currently logged in user.",
        "tags": [
          "Users"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/users/companies": {
      "get": {
        "summary": "Retrieve all companies the user has access to.",
        "description": "List of available companies can be configured by a privileged user, using field for allowed roles under the user settings.",
        "tags": [
          "Users"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.brainformatik.crm-v1+json": {
                "schema": {
                  "$ref": "#/components/schemas/CompaniesResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    }
  },
  "openapi": "3.0.2",
  "info": {
    "title": "brainX REST API",
    "description": "This is the REST API for programmatically accessing brainX.<br><br> Every action that is protected needs the Authorization header to be present.<br><br> For an easier start we provide a basic [Postman](https://www.postman.com/downloads/) Collection that you can [get here](postman.json). It automatically sets the auth token to every request. You only have to create an environment and provide the following variables:<br>\n  * **url**: the URL of your CRM without any additional path e.g. https://sub-domain.brainx.app<br>\n  * **userName**: the name of the user that should be used for login<br>\n  * **password**: the password of the user for login (no accessKey like for the previous API)\n\n\n**Rate Limit**<br><br> There is a rate limit of 60 requests/minute based on the IP address of the caller.  If you get over this limit, you will get a 429 response until you are allowed to make further requests. This is a sliding window, if you really have to make a lot of requests, you should wait a second after each request to avoid running into the limit.\n\n**Changelog**<br><br> *1.2.0*<br>\n  * Creating and editing records now runs the same field validation as the edit view of the CRM.\n    In addition to the mandatory field check this covers conditional mandatory fields, date dependencies (e.g. an end date must not be before its start date),\n    uniqueness rules, number limits and entity specific rules. A failed validation returns status 400 with the message\n    \"Validation failed: ...\" listing every field and the reason. Requests that were accepted before can now be rejected if the data violates such a rule.<br>\n\n\n*1.1.0*<br>\n  * Extended filter for list queries\n",
    "version": "1.2.0"
  },
  "security": [
    {
      "bearer": []
    }
  ],
  "servers": [
    {
      "url": "https://{subdomain}.brainx.app/api",
      "variables": {
        "subdomain": {
          "default": "ihr-system"
        }
      }
    }
  ]
}