[
  {
    "path": ".gitignore",
    "content": "site/\n.venv\n.idea\n"
  },
  {
    "path": "README.md",
    "content": "# EspoCRM Documentation\n\n### View documentation\n\n* [On the website](https://docs.espocrm.com)\n* [On this repository](docs/index.md)\n\n### How to build\n\nAssuming you have *python* and *pip* installed.\n\nInstall the packages:\n\n1. `pip install mkdocs`\n2. `pip install mdx_truly_sane_lists`\n3. `pip install mkdocs-material`\n\nCommand to build:\n\n```\nmkdocs build\n```\n\nCommand to build if using venv:\n```\n.venv/bin/mkdocs build\n```\n\nCommand to build on Windows:\n```\npython -m mkdocs build\n```\n"
  },
  {
    "path": "docs/_static/csv/bpm-examples.csv",
    "content": "name,targetType,isActive,data,description\n\"Example: Email reply catching\",Account,,\"{\"\"list\"\":[{\"\"type\"\":\"\"eventStart\"\",\"\"center\"\":{\"\"x\"\":100,\"\"y\"\":160},\"\"id\"\":\"\"9y6izy64v1\"\"},{\"\"type\"\":\"\"taskSendMessage\"\",\"\"center\"\":{\"\"x\"\":200,\"\"y\"\":160},\"\"doNotStore\"\":false,\"\"from\"\":\"\"system\"\",\"\"to\"\":\"\"targetEntity\"\",\"\"replyTo\"\":\"\"\"\",\"\"messageType\"\":\"\"Email\"\",\"\"optOutLink\"\":false,\"\"id\"\":\"\"a1r9e3g1ee\"\",\"\"text\"\":\"\"Send email to account\"\",\"\"emailTemplateName\"\":null,\"\"emailTemplateId\"\":null,\"\"description\"\":\"\"Select email template.\"\"},{\"\"startId\"\":\"\"9y6izy64v1\"\",\"\"endId\"\":\"\"a1r9e3g1ee\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"63d18vn5hw\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"gatewayEventBased\"\",\"\"center\"\":{\"\"x\"\":300,\"\"y\"\":160},\"\"id\"\":\"\"ximev2a5su\"\",\"\"text\"\":null,\"\"description\"\":\"\"Stops the flow until the first subsequent event is triggered.\"\"},{\"\"startId\"\":\"\"a1r9e3g1ee\"\",\"\"endId\"\":\"\"ximev2a5su\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"eigxf6kf3b\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventIntermediateMessageCatch\"\",\"\"center\"\":{\"\"x\"\":380,\"\"y\"\":160},\"\"repliedTo\"\":\"\"a1r9e3g1ee\"\",\"\"relatedTo\"\":null,\"\"messageType\"\":\"\"Email\"\",\"\"id\"\":\"\"076bji878y\"\",\"\"text\"\":\"\"Replied with 'yes'\"\",\"\"description\"\":\"\"Event will be triggered if the received email is a reply to the email sent by the process before and body contains word 'yes'\"\",\"\"conditionsFormula\"\":\"\"string\\\\contains(body, string\\\\lowerCase('yes'))\"\"},{\"\"type\"\":\"\"eventIntermediateTimerCatch\"\",\"\"center\"\":{\"\"x\"\":380,\"\"y\"\":260},\"\"timerBase\"\":null,\"\"timerShift\"\":24,\"\"timerShiftUnits\"\":\"\"hours\"\",\"\"timerShiftOperator\"\":\"\"plus\"\",\"\"timerFormula\"\":null,\"\"id\"\":\"\"5g9qccto4j\"\",\"\"text\"\":\"\"Wait 24h\"\",\"\"description\"\":null},{\"\"startId\"\":\"\"ximev2a5su\"\",\"\"endId\"\":\"\"5g9qccto4j\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"vzobuguik8\"\",\"\"type\"\":\"\"flow\"\"},{\"\"startId\"\":\"\"ximev2a5su\"\",\"\"endId\"\":\"\"076bji878y\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"ddeuegbdmn\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":480,\"\"y\"\":260},\"\"id\"\":\"\"smpn4950he\"\"},{\"\"startId\"\":\"\"5g9qccto4j\"\",\"\"endId\"\":\"\"smpn4950he\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"w8cy6l5tja\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":480,\"\"y\"\":160},\"\"id\"\":\"\"0st6bue5bz\"\",\"\"text\"\":\"\"Create task\"\",\"\"description\"\":\"\"You need also to assign the task to some user.\"\",\"\"actionList\"\":[{\"\"link\"\":\"\"Task\"\",\"\"fieldList\"\":[\"\"name\"\"],\"\"fields\"\":{\"\"name\"\":{\"\"subjectType\"\":\"\"value\"\",\"\"attributes\"\":{\"\"name\"\":\"\"Discuss about a possible deal\"\"}}},\"\"cid\"\":0,\"\"id\"\":\"\"27dhn9mrxs\"\",\"\"linkList\"\":[\"\"parent\"\"],\"\"formula\"\":\"\"\"\",\"\"entityType\"\":\"\"Task\"\",\"\"type\"\":\"\"createEntity\"\"}]},{\"\"startId\"\":\"\"076bji878y\"\",\"\"endId\"\":\"\"0st6bue5bz\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"wwft7n4nzu\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":580,\"\"y\"\":160},\"\"id\"\":\"\"znvksdm1ff\"\"},{\"\"startId\"\":\"\"0st6bue5bz\"\",\"\"endId\"\":\"\"znvksdm1ff\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"yqcx692xco\"\",\"\"type\"\":\"\"flow\"\"}],\"\"createdEntitiesData\"\":{\"\"a1r9e3g1ee\"\":{\"\"elementId\"\":\"\"a1r9e3g1ee\"\",\"\"actionId\"\":null,\"\"entityType\"\":\"\"Email\"\",\"\"numberId\"\":0,\"\"text\"\":\"\"Send email to account\"\"},\"\"0st6bue5bz_27dhn9mrxs\"\":{\"\"elementId\"\":\"\"0st6bue5bz\"\",\"\"actionId\"\":\"\"27dhn9mrxs\"\",\"\"link\"\":null,\"\"entityType\"\":\"\"Task\"\",\"\"numberId\"\":0}}}\",\"This example shows how it's possible to catch a reply to the email sent by the process.\n\n* This flowchart is not active. You need to set *Is Active* to make it runnable.\n\nClick on flow items bellow to see more info.\n\nThis process supposed to be started manually (from the account detail view > dropdown in top-right corner).\n \nYou can replace start event with the event of other type.\"\n\"Example: Sub-process\",Account,,\"{\"\"list\"\":[{\"\"type\"\":\"\"eventStart\"\",\"\"center\"\":{\"\"x\"\":40,\"\"y\"\":100},\"\"id\"\":\"\"dnce1dwk9c\"\",\"\"text\"\":\"\"Start manually\"\",\"\"description\"\":null},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":140,\"\"y\"\":100},\"\"id\"\":\"\"d0bwlpsqjb\"\",\"\"text\"\":\"\"Create opportunity\"\",\"\"description\"\":null,\"\"actionList\"\":[{\"\"link\"\":\"\"Opportunity\"\",\"\"fieldList\"\":[\"\"name\"\",\"\"stage\"\",\"\"closeDate\"\",\"\"amount\"\"],\"\"fields\"\":{\"\"name\"\":{\"\"subjectType\"\":\"\"value\"\",\"\"attributes\"\":{\"\"name\"\":\"\"New subscription\"\"}},\"\"stage\"\":{\"\"subjectType\"\":\"\"value\"\",\"\"attributes\"\":{\"\"stage\"\":\"\"Proposal\"\"}},\"\"closeDate\"\":{\"\"subjectType\"\":\"\"today\"\",\"\"shiftDays\"\":\"\"1\"\",\"\"attributes\"\":{},\"\"shiftUnit\"\":\"\"months\"\"},\"\"amount\"\":{\"\"subjectType\"\":\"\"value\"\",\"\"attributes\"\":{\"\"amount\"\":500,\"\"amountCurrency\"\":\"\"USD\"\"}}},\"\"cid\"\":0,\"\"id\"\":\"\"mo1mt5e7q1\"\",\"\"linkList\"\":[\"\"account\"\"],\"\"formula\"\":\"\"\"\",\"\"entityType\"\":\"\"Opportunity\"\",\"\"type\"\":\"\"createEntity\"\"}]},{\"\"startId\"\":\"\"dnce1dwk9c\"\",\"\"endId\"\":\"\"d0bwlpsqjb\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"tscf17xz0c\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"subProcess\"\",\"\"center\"\":{\"\"x\"\":240,\"\"y\"\":260},\"\"isExpanded\"\":true,\"\"triggeredByEvent\"\":false,\"\"dataList\"\":[{\"\"type\"\":\"\"eventStart\"\",\"\"center\"\":{\"\"x\"\":40,\"\"y\"\":80},\"\"id\"\":\"\"rfa7a1ten5\"\",\"\"text\"\":null,\"\"description\"\":\"\"The flow starts from Start Event once Sub-Process element is reached by the flow.\"\"},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":140,\"\"y\"\":80},\"\"id\"\":\"\"fwdhod2w40\"\",\"\"text\"\":\"\"Assign opportunity\"\",\"\"actionList\"\":[],\"\"description\"\":\"\"Here you can add 'Apply Assignment Rule' or 'Update Target Record' action.\"\"},{\"\"startId\"\":\"\"rfa7a1ten5\"\",\"\"endId\"\":\"\"fwdhod2w40\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"nk0635f6o5\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventIntermediateConditionalCatch\"\",\"\"center\"\":{\"\"x\"\":260,\"\"y\"\":80},\"\"id\"\":\"\"ya9l302iso\"\",\"\"text\"\":\"\"Opportunity is won\"\",\"\"conditionsAll\"\":[{\"\"comparison\"\":\"\"equals\"\",\"\"subjectType\"\":\"\"value\"\",\"\"cid\"\":0,\"\"fieldToCompare\"\":\"\"stage\"\",\"\"type\"\":\"\"all\"\",\"\"value\"\":\"\"Closed Won\"\"}],\"\"conditionsAny\"\":[],\"\"conditionsFormula\"\":\"\"\"\",\"\"description\"\":null},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":340,\"\"y\"\":80},\"\"id\"\":\"\"nj9rtq4sxs\"\"},{\"\"startId\"\":\"\"ya9l302iso\"\",\"\"endId\"\":\"\"nj9rtq4sxs\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"71idx7lyd3\"\",\"\"type\"\":\"\"flow\"\"},{\"\"startId\"\":\"\"fwdhod2w40\"\",\"\"endId\"\":\"\"ya9l302iso\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"o695oc3hqy\"\",\"\"type\"\":\"\"flow\"\"}],\"\"target\"\":\"\"created:d0bwlpsqjb_mo1mt5e7q1\"\",\"\"returnVariableList\"\":[],\"\"targetType\"\":\"\"Opportunity\"\",\"\"id\"\":\"\"d5fxlnoewa\"\",\"\"width\"\":395,\"\"height\"\":184,\"\"text\"\":\"\"Target is switched to opportunity within sub-process\"\",\"\"description\"\":null},{\"\"startId\"\":\"\"d0bwlpsqjb\"\",\"\"endId\"\":\"\"d5fxlnoewa\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"eozfn81pez\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventIntermediateTimerBoundary\"\",\"\"attachedToId\"\":\"\"d5fxlnoewa\"\",\"\"cancelActivity\"\":false,\"\"timerBase\"\":null,\"\"timerShift\"\":10,\"\"timerShiftUnits\"\":\"\"days\"\",\"\"timerShiftOperator\"\":\"\"plus\"\",\"\"timerFormula\"\":null,\"\"attachPosition\"\":\"\"bl4\"\",\"\"center\"\":{\"\"x\"\":100,\"\"y\"\":352},\"\"id\"\":\"\"bwf5gnjmh2\"\",\"\"text\"\":\"\"10 days passed\"\",\"\"description\"\":\"\"If 10 days passed and sub-process is still active then this event will be triggered. Since it is not interrupting, it won't stop the sub-process.\"\"},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":100,\"\"y\"\":460},\"\"id\"\":\"\"qd6ismf2r1\"\",\"\"text\"\":\"\"Notify user assigned to account\"\",\"\"actionList\"\":[{\"\"recipient\"\":\"\"link:assignedUser\"\",\"\"userIdList\"\":[],\"\"userNames\"\":{},\"\"cid\"\":0,\"\"id\"\":\"\"cccgw7wd87\"\",\"\"messageTemplate\"\":\"\"Opportunity for account {entity} has been in process for 10 days.\"\",\"\"specifiedTeamsIds\"\":[],\"\"specifiedTeamsNames\"\":{},\"\"type\"\":\"\"createNotification\"\"}],\"\"description\"\":null},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":100,\"\"y\"\":540},\"\"id\"\":\"\"bzuaili08f\"\",\"\"text\"\":null,\"\"description\"\":\"\"This will NOT stop the process, because there will still active flow items. It's a best practice to end any flow with End Event.\"\"},{\"\"startId\"\":\"\"qd6ismf2r1\"\",\"\"endId\"\":\"\"bzuaili08f\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"yx8275wtrt\"\",\"\"type\"\":\"\"flow\"\"},{\"\"startId\"\":\"\"bwf5gnjmh2\"\",\"\"endId\"\":\"\"qd6ismf2r1\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"4j2hubewis\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventIntermediateConditionalBoundary\"\",\"\"attachedToId\"\":\"\"d5fxlnoewa\"\",\"\"cancelActivity\"\":true,\"\"attachPosition\"\":\"\"bl1\"\",\"\"center\"\":{\"\"x\"\":220,\"\"y\"\":352},\"\"id\"\":\"\"i7rer4ire8\"\",\"\"text\"\":\"\"Opportunity is lost\"\",\"\"conditionsAll\"\":[{\"\"comparison\"\":\"\"equals\"\",\"\"subjectType\"\":\"\"value\"\",\"\"cid\"\":0,\"\"fieldToCompare\"\":\"\"created:d0bwlpsqjb_mo1mt5e7q1.stage\"\",\"\"type\"\":\"\"all\"\",\"\"value\"\":\"\"Closed Lost\"\"}],\"\"conditionsAny\"\":[],\"\"conditionsFormula\"\":\"\"\"\",\"\"description\"\":\"\"It's an interrupting event. It will stop the sub-process it's attached to.\"\"},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":220,\"\"y\"\":460},\"\"id\"\":\"\"t30fe2rbnm\"\",\"\"text\"\":\"\"Notify user assigned to account\"\",\"\"actionList\"\":[{\"\"recipient\"\":\"\"link:assignedUser\"\",\"\"userIdList\"\":[],\"\"userNames\"\":{},\"\"cid\"\":0,\"\"id\"\":\"\"qstbhs9m8a\"\",\"\"messageTemplate\"\":\"\"Opportunity for account {entity} is lost.\"\",\"\"specifiedTeamsIds\"\":[],\"\"specifiedTeamsNames\"\":{},\"\"type\"\":\"\"createNotification\"\"}],\"\"description\"\":null},{\"\"startId\"\":\"\"i7rer4ire8\"\",\"\"endId\"\":\"\"t30fe2rbnm\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"l0wsiyzsbo\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":220,\"\"y\"\":540},\"\"id\"\":\"\"m6krciw1ab\"\",\"\"text\"\":null,\"\"description\"\":\"\"The process will be stopped with this event, since there won't be any active flow items at that moment. It's a best practice to end any flow with End Event.\"\"},{\"\"startId\"\":\"\"t30fe2rbnm\"\",\"\"endId\"\":\"\"m6krciw1ab\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"lgt4082clq\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":520,\"\"y\"\":260},\"\"id\"\":\"\"r3co6n6vyx\"\",\"\"text\"\":\"\"Create task to arrange shipment\"\",\"\"actionList\"\":[{\"\"link\"\":\"\"Task\"\",\"\"fieldList\"\":[\"\"name\"\"],\"\"fields\"\":{\"\"name\"\":{\"\"subjectType\"\":\"\"value\"\",\"\"attributes\"\":{\"\"name\"\":\"\"Arrange shipment\"\"}}},\"\"cid\"\":0,\"\"id\"\":\"\"eatnd0zhrz\"\",\"\"linkList\"\":[\"\"account\"\"],\"\"formula\"\":\"\"\"\",\"\"entityType\"\":\"\"Task\"\",\"\"type\"\":\"\"createEntity\"\"}],\"\"description\"\":\"\"You can make this task assigned to some used. Edit the action and add Assigned User field.\"\"},{\"\"startId\"\":\"\"d5fxlnoewa\"\",\"\"endId\"\":\"\"r3co6n6vyx\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"3ktu0s122l\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":620,\"\"y\"\":260},\"\"id\"\":\"\"oxcrq8pqoh\"\"},{\"\"startId\"\":\"\"r3co6n6vyx\"\",\"\"endId\"\":\"\"oxcrq8pqoh\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"f7nkp9lajf\"\",\"\"type\"\":\"\"flow\"\"}],\"\"createdEntitiesData\"\":{\"\"d0bwlpsqjb_mo1mt5e7q1\"\":{\"\"elementId\"\":\"\"d0bwlpsqjb\"\",\"\"actionId\"\":\"\"mo1mt5e7q1\"\",\"\"link\"\":null,\"\"entityType\"\":\"\"Opportunity\"\",\"\"numberId\"\":0},\"\"r3co6n6vyx_eatnd0zhrz\"\":{\"\"elementId\"\":\"\"r3co6n6vyx\"\",\"\"actionId\"\":\"\"eatnd0zhrz\"\",\"\"link\"\":null,\"\"entityType\"\":\"\"Task\"\",\"\"numberId\"\":0}}}\",\"This example shows how it's regular sub-processes work in BPM.\n\n* This flowchart is not active. You need to set *Is Active* to make it runnable.\n\nClick on flow items bellow to see more info.\n\nThis process supposed to be started manually (from the account detail view > dropdown in top-right corner).\n \nYou can replace start event with the event of other type.\"\n\"Example: User task\",Lead,,\"{\"\"list\"\":[{\"\"type\"\":\"\"taskUser\"\",\"\"center\"\":{\"\"x\"\":160,\"\"y\"\":120},\"\"actionType\"\":\"\"Approve\"\",\"\"assignmentType\"\":\"\"\"\",\"\"instructions\"\":null,\"\"name\"\":\"\"Approve lead: '{$name}'\"\",\"\"targetTeamId\"\":null,\"\"target\"\":\"\"\"\",\"\"id\"\":\"\"450yvismmk\"\",\"\"text\"\":\"\"User needs to approve lead\"\",\"\"targetTeamName\"\":null,\"\"description\"\":\"\"You need to specify *Assignment* field. E.g. you can make the task to be assigned to a specific user, who is a sales manager or apply round-robin among users of a specific team.\\n\\nThe execution of the flow will be stopped until the user task is resolved.\\n\\n\"\"},{\"\"type\"\":\"\"eventStartConditional\"\",\"\"center\"\":{\"\"x\"\":60,\"\"y\"\":120},\"\"triggerType\"\":\"\"afterRecordCreated\"\",\"\"isInterrupting\"\":false,\"\"id\"\":\"\"hmchah0hs2\"\",\"\"text\"\":\"\"Lead created & status is 'New'\"\",\"\"description\"\":null,\"\"conditionsAll\"\":[{\"\"comparison\"\":\"\"equals\"\",\"\"subjectType\"\":\"\"value\"\",\"\"cid\"\":0,\"\"fieldToCompare\"\":\"\"status\"\",\"\"value\"\":\"\"New\"\",\"\"type\"\":\"\"all\"\"}],\"\"conditionsAny\"\":[],\"\"conditionsFormula\"\":\"\"\"\"},{\"\"startId\"\":\"\"hmchah0hs2\"\",\"\"endId\"\":\"\"450yvismmk\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"4xiy8mazdh\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"gatewayExclusive\"\",\"\"center\"\":{\"\"x\"\":260,\"\"y\"\":120},\"\"id\"\":\"\"kw4z4p00jg\"\",\"\"text\"\":null,\"\"defaultFlowId\"\":\"\"p0md4yzc4c\"\",\"\"flowList\"\":[{\"\"id\"\":\"\"m4hu3o0ykw\"\",\"\"conditionsAll\"\":[{\"\"comparison\"\":\"\"equals\"\",\"\"subjectType\"\":\"\"value\"\",\"\"cid\"\":0,\"\"fieldToCompare\"\":\"\"created:450yvismmk.resolution\"\",\"\"value\"\":\"\"Approved\"\",\"\"type\"\":\"\"all\"\"}],\"\"conditionsAny\"\":[],\"\"conditionsFormula\"\":\"\"\"\"}],\"\"description\"\":null},{\"\"startId\"\":\"\"450yvismmk\"\",\"\"endId\"\":\"\"kw4z4p00jg\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"zvzlrejg7j\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":380,\"\"y\"\":180},\"\"id\"\":\"\"ftj2vk8jyg\"\",\"\"text\"\":\"\"Change status to 'Dead'\"\",\"\"actionList\"\":[{\"\"fieldList\"\":[\"\"status\"\"],\"\"fields\"\":{\"\"status\"\":{\"\"subjectType\"\":\"\"value\"\",\"\"attributes\"\":{\"\"status\"\":\"\"Dead\"\"}}},\"\"cid\"\":0,\"\"id\"\":\"\"uapdcjlwh3\"\",\"\"formula\"\":\"\"\"\",\"\"type\"\":\"\"updateEntity\"\"}],\"\"description\"\":null},{\"\"startId\"\":\"\"kw4z4p00jg\"\",\"\"endId\"\":\"\"ftj2vk8jyg\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"p0md4yzc4c\"\",\"\"type\"\":\"\"flow\"\",\"\"isDefault\"\":true,\"\"text\"\":\"\"not\"\",\"\"description\"\":null},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":480,\"\"y\"\":180},\"\"id\"\":\"\"sbye7srr81\"\",\"\"text\"\":null,\"\"description\"\":null},{\"\"startId\"\":\"\"ftj2vk8jyg\"\",\"\"endId\"\":\"\"sbye7srr81\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"0rzdao21lz\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":380,\"\"y\"\":60},\"\"id\"\":\"\"dro3qss4io\"\",\"\"text\"\":\"\"Assign lead, change status to 'Assigned'\"\",\"\"actionList\"\":[{\"\"fieldList\"\":[\"\"status\"\"],\"\"fields\"\":{\"\"status\"\":{\"\"subjectType\"\":\"\"value\"\",\"\"attributes\"\":{\"\"status\"\":\"\"Assigned\"\"}}},\"\"cid\"\":0,\"\"id\"\":\"\"re6s604de8\"\",\"\"formula\"\":\"\"\"\",\"\"type\"\":\"\"updateEntity\"\"}],\"\"description\"\":\"\"Add *Apply Assigned Rule* action or use *Update Target Record* to set the specific Assigned User.\"\"},{\"\"startId\"\":\"\"kw4z4p00jg\"\",\"\"endId\"\":\"\"dro3qss4io\"\",\"\"startDirection\"\":\"\"u\"\",\"\"id\"\":\"\"m4hu3o0ykw\"\",\"\"type\"\":\"\"flow\"\",\"\"isDefault\"\":false,\"\"text\"\":\"\"approved\"\",\"\"description\"\":null},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":480,\"\"y\"\":60},\"\"id\"\":\"\"7gp8swt3c2\"\",\"\"text\"\":null,\"\"description\"\":null},{\"\"startId\"\":\"\"dro3qss4io\"\",\"\"endId\"\":\"\"7gp8swt3c2\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"l0kizq3kbg\"\",\"\"type\"\":\"\"flow\"\"}],\"\"createdEntitiesData\"\":{\"\"450yvismmk\"\":{\"\"elementId\"\":\"\"450yvismmk\"\",\"\"actionId\"\":null,\"\"entityType\"\":\"\"BpmnUserTask\"\",\"\"numberId\"\":0,\"\"text\"\":\"\"User needs to approve lead\"\"}}}\",\"This example shows how it's possible to make BPM process to interact with a user.\n\n* This flowchart is not active. You need to set *Is Active* to make it runnable. \n\nClick on flow items bellow to see more info.\n\nThis example is for Contact entity type. You can create a similar flowchart for any other entity type.\n\n\"\n\"Example: Tracking URLs\",Contact,,\"{\"\"list\"\":[{\"\"type\"\":\"\"eventStart\"\",\"\"center\"\":{\"\"x\"\":60,\"\"y\"\":120},\"\"id\"\":\"\"kabctmad37\"\",\"\"text\"\":\"\"Start event\"\",\"\"description\"\":\"\"You can start a process manually, from the contact detail view > menu in the top-right corner.\\n\\nYou can use *Conditional Start Event* instead of this one. To start the process automatically once a contact meets a specific criteria.\"\"},{\"\"type\"\":\"\"taskSendMessage\"\",\"\"center\"\":{\"\"x\"\":160,\"\"y\"\":120},\"\"doNotStore\"\":false,\"\"from\"\":\"\"system\"\",\"\"to\"\":\"\"targetEntity\"\",\"\"replyTo\"\":\"\"\"\",\"\"messageType\"\":\"\"Email\"\",\"\"optOutLink\"\":false,\"\"id\"\":\"\"zlq87fmo83\"\",\"\"text\"\":\"\"Send tracking link to customer\"\",\"\"emailTemplateName\"\":null,\"\"emailTemplateId\"\":null,\"\"description\"\":\"\"Create and select an email template. Use a placeholder of your tracking URL in the template body as URL of a link.\"\"},{\"\"startId\"\":\"\"kabctmad37\"\",\"\"endId\"\":\"\"zlq87fmo83\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"s82mkwpspe\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"gatewayEventBased\"\",\"\"center\"\":{\"\"x\"\":280,\"\"y\"\":120},\"\"id\"\":\"\"vcon04sppd\"\",\"\"text\"\":null,\"\"description\"\":\"\"This will stop execution of the flow until any subsequent event is triggered.\"\"},{\"\"startId\"\":\"\"zlq87fmo83\"\",\"\"endId\"\":\"\"vcon04sppd\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"6weyw6rep4\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventIntermediateTimerCatch\"\",\"\"center\"\":{\"\"x\"\":360,\"\"y\"\":120},\"\"timerBase\"\":null,\"\"timerShift\"\":7,\"\"timerShiftUnits\"\":\"\"days\"\",\"\"timerShiftOperator\"\":\"\"plus\"\",\"\"timerFormula\"\":null,\"\"id\"\":\"\"hy7u5o7agx\"\",\"\"text\"\":\"\"Time expired\"\",\"\"description\"\":\"\"We 7 days expire, the event will be triggered. It will cancel the concurrent pending event 'Link clicked'.\"\"},{\"\"type\"\":\"\"eventIntermediateSignalCatch\"\",\"\"center\"\":{\"\"x\"\":360,\"\"y\"\":220},\"\"signal\"\":\"\"clickUrl.Contact.{$id}.5d8206aa9d76df4c8\"\",\"\"id\"\":\"\"isu1v13nfx\"\",\"\"text\"\":\"\"Link clicked\"\",\"\"description\"\":\"\"This event is triggered once a customer clicked the link.\\n\\nReplace `5d8206aa9d76df4c8` with the real ID of your tracking URL. ID can be obtained from the address bar or from the placeholder of the tracking URL.\"\"},{\"\"startId\"\":\"\"vcon04sppd\"\",\"\"endId\"\":\"\"hy7u5o7agx\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"fxvfwqph8o\"\",\"\"type\"\":\"\"flow\"\"},{\"\"startId\"\":\"\"vcon04sppd\"\",\"\"endId\"\":\"\"isu1v13nfx\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"7fjh4skior\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":440,\"\"y\"\":120},\"\"id\"\":\"\"oii6la4bfz\"\",\"\"text\"\":null,\"\"description\"\":null},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":460,\"\"y\"\":220},\"\"id\"\":\"\"y68y98mltp\"\",\"\"text\"\":\"\"Do something\"\",\"\"description\"\":\"\"Here you can make some actions with the contact. E.g. update some field with *Update Target Record* action.\"\",\"\"actionList\"\":[]},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":560,\"\"y\"\":220},\"\"id\"\":\"\"wqo430vyvs\"\",\"\"text\"\":null,\"\"description\"\":null},{\"\"startId\"\":\"\"hy7u5o7agx\"\",\"\"endId\"\":\"\"oii6la4bfz\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"0yxkcxh31f\"\",\"\"type\"\":\"\"flow\"\"},{\"\"startId\"\":\"\"isu1v13nfx\"\",\"\"endId\"\":\"\"y68y98mltp\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"hq9xnk35rt\"\",\"\"type\"\":\"\"flow\"\"},{\"\"startId\"\":\"\"y68y98mltp\"\",\"\"endId\"\":\"\"wqo430vyvs\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"xm0tnpk22u\"\",\"\"type\"\":\"\"flow\"\"}],\"\"createdEntitiesData\"\":{\"\"zlq87fmo83\"\":{\"\"elementId\"\":\"\"zlq87fmo83\"\",\"\"actionId\"\":null,\"\"entityType\"\":\"\"Email\"\",\"\"numberId\"\":0,\"\"text\"\":\"\"Send tracking link to customer\"\"}}}\",\"This example shows how it's possible to automatically interact with a customer via emails.\n\n* This flowchart is not active. You need to set *Is Active* to make it runnable.\n* You need to create Tracking URL at Campaigns > top-right menu > Tracking URLs.  Tracking URLs. Create URL and obtain a generated placeholder (example: `{trackingUrl:5d8206aa9d76df4c8}`). Use that placeholder as a URL of the link in your email template. Example: `<a href=\"\"{trackingUrl:5d8206aa9d76df4c8}\"\">Click me</a>`.\n\nClick on flow items bellow to see more info.\n\nThis example is for Contact entity type. You can create a similar flowchart for Account or Lead.\n\n\"\n\"Example: Drip email campaign\",Lead,,\"{\"\"list\"\":[{\"\"type\"\":\"\"eventStartSignal\"\",\"\"center\"\":{\"\"x\"\":40,\"\"y\"\":100},\"\"signal\"\":\"\"@leadCapture.LEAD_CAPTURE_ID\"\",\"\"isInterrupting\"\":false,\"\"id\"\":\"\"tj7y8xjxel\"\",\"\"text\"\":\"\"Lead subscribed\"\",\"\"description\"\":\"\"Replace *LEAD_CAPTURE_ID* with ID for the Lead Capture record. \\n\\nID can be obtained from the address bar on the detail view of Lead Capture record. Administration > Lead Capture > click on the record.\\n\\nYou can also start the process manually, from the lead detail view > menu in the top-right corner.\\n\\nYou can also use *Conditional Start Event* instead of this one. To start the campaign once a lead meets a specific criteria.\"\"},{\"\"type\"\":\"\"taskSendMessage\"\",\"\"center\"\":{\"\"x\"\":140,\"\"y\"\":100},\"\"doNotStore\"\":false,\"\"from\"\":\"\"system\"\",\"\"to\"\":\"\"targetEntity\"\",\"\"replyTo\"\":\"\"\"\",\"\"messageType\"\":\"\"Email\"\",\"\"optOutLink\"\":true,\"\"id\"\":\"\"vv3g2qreo7\"\",\"\"text\"\":\"\"Send welcome email\"\",\"\"emailTemplateName\"\":null,\"\"emailTemplateId\"\":null,\"\"description\"\":\"\"Select email template. \"\"},{\"\"startId\"\":\"\"tj7y8xjxel\"\",\"\"endId\"\":\"\"vv3g2qreo7\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"18tm84gton\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventIntermediateTimerCatch\"\",\"\"center\"\":{\"\"x\"\":240,\"\"y\"\":100},\"\"timerBase\"\":null,\"\"timerShift\"\":7,\"\"timerShiftUnits\"\":\"\"days\"\",\"\"timerShiftOperator\"\":\"\"plus\"\",\"\"timerFormula\"\":null,\"\"id\"\":\"\"nl6fasw5ey\"\",\"\"text\"\":\"\"Wait 7 days\"\",\"\"description\"\":\"\"This will stop a flow execution for 7 days.\"\"},{\"\"startId\"\":\"\"vv3g2qreo7\"\",\"\"endId\"\":\"\"nl6fasw5ey\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"katp0qxsd7\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"taskSendMessage\"\",\"\"center\"\":{\"\"x\"\":280,\"\"y\"\":200},\"\"doNotStore\"\":false,\"\"from\"\":\"\"system\"\",\"\"to\"\":\"\"targetEntity\"\",\"\"replyTo\"\":\"\"\"\",\"\"messageType\"\":\"\"Email\"\",\"\"optOutLink\"\":true,\"\"id\"\":\"\"35pbf4obcs\"\",\"\"text\"\":\"\"Send email #1\"\",\"\"emailTemplateName\"\":null,\"\"emailTemplateId\"\":null,\"\"description\"\":\"\"Select email template.\"\"},{\"\"startId\"\":\"\"nl6fasw5ey\"\",\"\"endId\"\":\"\"35pbf4obcs\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"0v29rrcw0z\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventIntermediateTimerCatch\"\",\"\"center\"\":{\"\"x\"\":380,\"\"y\"\":200},\"\"timerBase\"\":null,\"\"timerShift\"\":7,\"\"timerShiftUnits\"\":\"\"days\"\",\"\"timerShiftOperator\"\":\"\"plus\"\",\"\"timerFormula\"\":null,\"\"id\"\":\"\"tvzgqpzarn\"\",\"\"text\"\":\"\"Wait 7 days\"\",\"\"description\"\":\"\"This will stop a flow execution for 7 days.\"\"},{\"\"startId\"\":\"\"35pbf4obcs\"\",\"\"endId\"\":\"\"tvzgqpzarn\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"rs87q5e62u\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"gatewayExclusive\"\",\"\"center\"\":{\"\"x\"\":460,\"\"y\"\":260},\"\"id\"\":\"\"qul8pya34q\"\",\"\"text\"\":\"\"Lead is converted\"\",\"\"description\"\":null,\"\"defaultFlowId\"\":\"\"la5nv59bb1\"\",\"\"flowList\"\":[{\"\"id\"\":\"\"ztv11gwdiu\"\",\"\"conditionsAll\"\":[{\"\"comparison\"\":\"\"equals\"\",\"\"subjectType\"\":\"\"value\"\",\"\"cid\"\":0,\"\"fieldToCompare\"\":\"\"status\"\",\"\"value\"\":\"\"Converted\"\",\"\"type\"\":\"\"all\"\"}],\"\"conditionsAny\"\":[],\"\"conditionsFormula\"\":\"\"\"\"}]},{\"\"startId\"\":\"\"tvzgqpzarn\"\",\"\"endId\"\":\"\"qul8pya34q\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"ylwrry53ss\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"taskSendMessage\"\",\"\"center\"\":{\"\"x\"\":560,\"\"y\"\":320},\"\"doNotStore\"\":false,\"\"from\"\":\"\"system\"\",\"\"to\"\":\"\"targetEntity\"\",\"\"replyTo\"\":\"\"\"\",\"\"messageType\"\":\"\"Email\"\",\"\"optOutLink\"\":true,\"\"id\"\":\"\"jnkhc4jx17\"\",\"\"text\"\":\"\"Send email #2-c\"\",\"\"emailTemplateName\"\":null,\"\"emailTemplateId\"\":null,\"\"description\"\":\"\"Select email template. \"\"},{\"\"type\"\":\"\"taskSendMessage\"\",\"\"center\"\":{\"\"x\"\":360,\"\"y\"\":320},\"\"doNotStore\"\":false,\"\"from\"\":\"\"system\"\",\"\"to\"\":\"\"targetEntity\"\",\"\"replyTo\"\":\"\"\"\",\"\"messageType\"\":\"\"Email\"\",\"\"optOutLink\"\":true,\"\"id\"\":\"\"z614240ac9\"\",\"\"text\"\":\"\"Send email #2\"\",\"\"emailTemplateName\"\":null,\"\"emailTemplateId\"\":null,\"\"description\"\":\"\"Select email template. \"\"},{\"\"startId\"\":\"\"qul8pya34q\"\",\"\"endId\"\":\"\"jnkhc4jx17\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"ztv11gwdiu\"\",\"\"type\"\":\"\"flow\"\",\"\"isDefault\"\":false,\"\"text\"\":\"\"yes\"\",\"\"description\"\":null},{\"\"startId\"\":\"\"qul8pya34q\"\",\"\"endId\"\":\"\"z614240ac9\"\",\"\"startDirection\"\":\"\"l\"\",\"\"id\"\":\"\"la5nv59bb1\"\",\"\"type\"\":\"\"flow\"\",\"\"isDefault\"\":true,\"\"text\"\":\"\"no\"\",\"\"description\"\":null},{\"\"type\"\":\"\"gatewayExclusive\"\",\"\"center\"\":{\"\"x\"\":460,\"\"y\"\":380},\"\"id\"\":\"\"8td5tjelmv\"\"},{\"\"startId\"\":\"\"jnkhc4jx17\"\",\"\"endId\"\":\"\"8td5tjelmv\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"cv25n3sry1\"\",\"\"type\"\":\"\"flow\"\"},{\"\"startId\"\":\"\"z614240ac9\"\",\"\"endId\"\":\"\"8td5tjelmv\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"ylupvbttcf\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventIntermediateTimerCatch\"\",\"\"center\"\":{\"\"x\"\":460,\"\"y\"\":460},\"\"timerBase\"\":null,\"\"timerShift\"\":30,\"\"timerShiftUnits\"\":\"\"days\"\",\"\"timerShiftOperator\"\":\"\"plus\"\",\"\"timerFormula\"\":null,\"\"id\"\":\"\"1st7mkgevh\"\",\"\"text\"\":\"\"Wait 30 days\"\",\"\"description\"\":null},{\"\"startId\"\":\"\"8td5tjelmv\"\",\"\"endId\"\":\"\"1st7mkgevh\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"avlmd4qzcy\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"taskSendMessage\"\",\"\"center\"\":{\"\"x\"\":560,\"\"y\"\":460},\"\"doNotStore\"\":false,\"\"from\"\":\"\"system\"\",\"\"to\"\":\"\"targetEntity\"\",\"\"replyTo\"\":\"\"\"\",\"\"messageType\"\":\"\"Email\"\",\"\"optOutLink\"\":true,\"\"id\"\":\"\"wxpeoqmqto\"\",\"\"text\"\":\"\"Send email #3\"\",\"\"emailTemplateName\"\":null,\"\"emailTemplateId\"\":null,\"\"description\"\":\"\"Select email template. \"\"},{\"\"startId\"\":\"\"1st7mkgevh\"\",\"\"endId\"\":\"\"wxpeoqmqto\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"m0jfvpcul9\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"task\"\",\"\"center\"\":{\"\"x\"\":560,\"\"y\"\":560},\"\"id\"\":\"\"g5j1ksct0e\"\",\"\"text\"\":\"\"Update lead\"\",\"\"description\"\":\"\"Here you can update the lead record. For example: set some field to indicate that the lead has finished the campaign.\\n\\nEdit *Update Target Record* action to specify what to update.\"\",\"\"actionList\"\":[{\"\"fieldList\"\":[],\"\"fields\"\":{},\"\"cid\"\":0,\"\"id\"\":\"\"y7s7rqp9rx\"\",\"\"formula\"\":\"\"\"\",\"\"type\"\":\"\"updateEntity\"\"}]},{\"\"startId\"\":\"\"wxpeoqmqto\"\",\"\"endId\"\":\"\"g5j1ksct0e\"\",\"\"startDirection\"\":\"\"d\"\",\"\"id\"\":\"\"x9hwxkda4m\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":660,\"\"y\"\":560},\"\"id\"\":\"\"8irjncf90g\"\",\"\"text\"\":\"\"End campaign\"\",\"\"description\"\":null},{\"\"startId\"\":\"\"g5j1ksct0e\"\",\"\"endId\"\":\"\"8irjncf90g\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"rb39zoq635\"\",\"\"type\"\":\"\"flow\"\"},{\"\"type\"\":\"\"eventSubProcess\"\",\"\"center\"\":{\"\"x\"\":100,\"\"y\"\":360},\"\"isExpanded\"\":true,\"\"triggeredByEvent\"\":true,\"\"dataList\"\":[{\"\"type\"\":\"\"eventStartSignal\"\",\"\"center\"\":{\"\"x\"\":40,\"\"y\"\":40},\"\"signal\"\":\"\"optOut.Lead.{$id}\"\",\"\"isInterrupting\"\":true,\"\"id\"\":\"\"g2r3zm7c5m\"\",\"\"text\"\":\"\"Lead opted-out\"\",\"\"description\"\":\"\"Do NOT change the signal name above.\\n\\nThis event is interrupting, meaning it will stop the parent process once triggered, so the campaign will be stopped.\"\"},{\"\"type\"\":\"\"eventEnd\"\",\"\"center\"\":{\"\"x\"\":140,\"\"y\"\":40},\"\"id\"\":\"\"9ezcdbezdj\"\"},{\"\"startId\"\":\"\"g2r3zm7c5m\"\",\"\"endId\"\":\"\"9ezcdbezdj\"\",\"\"startDirection\"\":\"\"r\"\",\"\"id\"\":\"\"4pz5fd6hh5\"\",\"\"type\"\":\"\"flow\"\"}],\"\"target\"\":\"\"\"\",\"\"targetType\"\":\"\"Lead\"\",\"\"id\"\":\"\"pq3dd59hsq\"\",\"\"eventStartData\"\":{\"\"type\"\":\"\"eventStartSignal\"\",\"\"center\"\":{\"\"x\"\":60,\"\"y\"\":40},\"\"signal\"\":\"\"optOut.Lead.{$id}\"\",\"\"isInterrupting\"\":true,\"\"id\"\":\"\"g2r3zm7c5m\"\",\"\"text\"\":\"\"Lead opted-out\"\",\"\"description\"\":\"\"Do NOT change the signal name above.\\n\\nThis event is interrupting, meaning it will stop the parent process once triggered, so the campaign will be stopped.\"\"},\"\"width\"\":189,\"\"height\"\":121}],\"\"createdEntitiesData\"\":{\"\"vv3g2qreo7\"\":{\"\"elementId\"\":\"\"vv3g2qreo7\"\",\"\"actionId\"\":null,\"\"entityType\"\":\"\"Email\"\",\"\"numberId\"\":0,\"\"text\"\":\"\"Send welcome email\"\"},\"\"35pbf4obcs\"\":{\"\"elementId\"\":\"\"35pbf4obcs\"\",\"\"actionId\"\":null,\"\"entityType\"\":\"\"Email\"\",\"\"numberId\"\":1,\"\"text\"\":\"\"Send email #1\"\"},\"\"jnkhc4jx17\"\":{\"\"elementId\"\":\"\"jnkhc4jx17\"\",\"\"actionId\"\":null,\"\"entityType\"\":\"\"Email\"\",\"\"numberId\"\":2,\"\"text\"\":\"\"Send email #2-c\"\"},\"\"z614240ac9\"\":{\"\"elementId\"\":\"\"z614240ac9\"\",\"\"actionId\"\":null,\"\"entityType\"\":\"\"Email\"\",\"\"numberId\"\":3,\"\"text\"\":\"\"Send email #2\"\"},\"\"wxpeoqmqto\"\":{\"\"elementId\"\":\"\"wxpeoqmqto\"\",\"\"actionId\"\":null,\"\"entityType\"\":\"\"Email\"\",\"\"numberId\"\":4,\"\"text\"\":\"\"Send email #3\"\"}}}\",\"This example show how it's possible to run drip campaigns with BPM.\n\n* This flowchart is not active. You need to set *Is Active* to make it runnable.\n* You need to edit Start Event to specify ID of a lead capture record.\n* You need to specify email templates for each 'Send Message' tasks.\n\nClick on flow items bellow to see more info.\"\n"
  },
  {
    "path": "docs/_static/scripts/backup-docker-container.sh",
    "content": "#!/bin/bash\n\n# This script creates a backup of an EspoCRM Docker container, including both the database and files.\n#\n# EspoCRM - Open Source CRM application.\n# Copyright (C) 2014-2026 EspoCRM, Inc.\n# Website: https://www.espocrm.com\n\nset -e\n\nfunction printExitError() {\n    local message=\"$1\"\n\n    local red='\\033[0;31m'\n    local default='\\033[0m'\n\n    printf \"\\n${red}ERROR${default}: ${message}\\n\"\n    exit 1\n}\n\nDEFAULT_ESPOCRM_CONTAINER=\"espocrm\"\nDEFAULT_BACKUP_PATH=\"$(pwd)\"\n\nprintf \"NOTICE\\nThis script is designed to work only with the official EspoCRM Docker image:\\nhttps://docs.espocrm.com/administration/docker/installation/#install-espocrm-with-docker-compose.\\n\\n\"\nsleep 1\n\nif [ -z \"$1\" ]; then\n    echo \"Enter an EspoCRM container name ($DEFAULT_ESPOCRM_CONTAINER):\"\n\n    read ESPOCRM_CONTAINER\n\n    if [ -z \"$ESPOCRM_CONTAINER\" ]; then\n        ESPOCRM_CONTAINER=\"$DEFAULT_ESPOCRM_CONTAINER\"\n    fi\nelse\n    ESPOCRM_CONTAINER=\"$1\"\nfi\n\nif [ -z \"$2\" ]; then\n    echo \"Enter a full path to backup directory ($DEFAULT_BACKUP_PATH):\"\n\n    read BACKUP_PATH\n\n    if [ -z \"$BACKUP_PATH\" ]; then\n        BACKUP_PATH=\"$DEFAULT_BACKUP_PATH\"\n    fi\nelse\n    BACKUP_PATH=\"$2\"\nfi\n\n# --- Validate ---\n\nif [ ! -d \"$BACKUP_PATH\" ]; then\n    mkdir -p \"$BACKUP_PATH\" || printExitError \"Unable to create the directory '$BACKUP_PATH'\"\nfi\n\nif [ ! -w \"$BACKUP_PATH\" ]; then\n    printExitError \"Backup directory '$BACKUP_PATH' is not writable\"\nfi\n\nDB_CONTAINER=$(docker exec \"$ESPOCRM_CONTAINER\" printenv ESPOCRM_DATABASE_HOST || echo \"\")\n\nif [ -z \"$DB_CONTAINER\" ]; then\n    printExitError \"Unable to determine the database container.\"\nfi\n\nDB_NAME=$(docker exec \"$ESPOCRM_CONTAINER\" printenv ESPOCRM_DATABASE_NAME || echo \"espocrm\")\nDB_USER=$(docker exec \"$ESPOCRM_CONTAINER\" printenv ESPOCRM_DATABASE_USER || echo \"espocrm\")\nDB_PASS=$(docker exec \"$ESPOCRM_CONTAINER\" printenv ESPOCRM_DATABASE_PASSWORD || echo \"\")\n\nif ! docker ps --format '{{.Names}}' | grep -q \"^${ESPOCRM_CONTAINER}$\"; then\n    printExitError \"Container '$ESPOCRM_CONTAINER' is not running\"\nfi\n\nif ! docker ps --format '{{.Names}}' | grep -q \"^${DB_CONTAINER}$\"; then\n    printExitError \"Container '$DB_CONTAINER' is not running\"\nfi\n\nif [ -z \"$DB_PASS\" ]; then\n    printExitError \"Unable to determine the database from container environment\"\nfi\n\n# --- Prepare temp dir and archive name ---\n\nBACKUP_ARCHIVE_NAME=\"$(date +'%Y-%m-%d_%H%M%S').tar.gz\"\nTEMP_DIR=\"$BACKUP_PATH/espocrm_backup_tmp\"\n\nmkdir -p \"$TEMP_DIR\"\n\n# --- Database backup ---\n\necho \">>> Backing up database '$DB_NAME'...\"\n\nDB_VERSION=$(docker exec \"$DB_CONTAINER\" mariadb --version 2>/dev/null || docker exec \"$DB_CONTAINER\" mysql --version 2>/dev/null)\n\nif echo \"$DB_VERSION\" | grep -qi \"mariadb\"; then\n    DUMP_CMD=\"mariadb-dump\"\nelse\n    DUMP_CMD=\"mysqldump\"\nfi\n\ndocker exec \"$DB_CONTAINER\" \\\n    $DUMP_CMD --user=\"$DB_USER\" --password=\"$DB_PASS\" \"$DB_NAME\" \\\n    > \"$TEMP_DIR/db.sql\" || printExitError \"Unable to create a backup for the database '$DB_NAME'\"\n\ntar -czf \"$TEMP_DIR/db.tar.gz\" -C \"$TEMP_DIR\" \"db.sql\"\nrm \"$TEMP_DIR/db.sql\"\n\necho \">>> Database backup done.\"\n\n# --- Files backup ---\n\necho \">>> Backing up EspoCRM files...\"\n\ndocker run --rm \\\n  --volumes-from \"${ESPOCRM_CONTAINER}\" \\\n  -v \"${TEMP_DIR}:/backup\" \\\n  alpine tar czf /backup/files.tar.gz -C /var/www/html . > /dev/null 2>&1\n\necho \">>> Files backup done.\"\n\n# --- Bundle into single archive ---\n\necho \">>> Creating final archive...\"\n\ntar czf \"$BACKUP_PATH/$BACKUP_ARCHIVE_NAME\" -C \"$TEMP_DIR\" .\n\n# --- Cleanup ---\n\nrm -rf \"$TEMP_DIR\"\n\necho \"\"\necho \"Backup created at '$BACKUP_PATH/$BACKUP_ARCHIVE_NAME'.\"\n"
  },
  {
    "path": "docs/_static/scripts/backup.sh",
    "content": "#!/bin/bash\n\n# This script creates a backup of an EspoCRM installation, including both the database and files.\n#\n# EspoCRM - Open Source CRM application.\n# Copyright (C) 2014-2026 EspoCRM, Inc.\n# Website: https://www.espocrm.com\n\nset -e\n\nfunction printExitError() {\n    local message=\"$1\"\n\n    local red='\\033[0;31m'\n    local default='\\033[0m'\n\n    printf \"\\n${red}ERROR${default}: ${message}\\n\"\n    exit 1\n}\n\nDEFAULT_PATH_TO_ESPO=\"/var/www/html\"\nDEFAULT_BACKUP_PATH=$(pwd)\n\nif [ -z \"$1\" ]; then\n    echo \"Enter a full path to EspoCRM directory ($DEFAULT_PATH_TO_ESPO):\"\n\n    read PATH_TO_ESPO\n    if [ -z \"$PATH_TO_ESPO\" ]; then\n        PATH_TO_ESPO=\"$DEFAULT_PATH_TO_ESPO\"\n    fi\nelse\n    PATH_TO_ESPO=\"$1\"\nfi\n\nif [ ! -d \"$PATH_TO_ESPO\" ]; then\n    printExitError \"The directory '$PATH_TO_ESPO' does not exist\"\nfi\n\nif [ ! -r \"$PATH_TO_ESPO\" ]; then\n    printExitError \"The directory '$PATH_TO_ESPO' is not readable\"\nfi\n\nif [ -z \"$2\" ]; then\n    echo \"Enter a full path to backup directory ($DEFAULT_BACKUP_PATH):\"\n\n    read BACKUP_PATH\n    if [ -z \"$BACKUP_PATH\" ]; then\n        BACKUP_PATH=\"$DEFAULT_BACKUP_PATH\"\n    fi\nelse\n    BACKUP_PATH=\"$2\"\nfi\n\nif [ ! -d \"$BACKUP_PATH\" ]; then\n    mkdir -p \"$BACKUP_PATH\" || printExitError \"Unable to create the directory '$BACKUP_PATH'\"\nfi\n\nif [ ! -w \"$BACKUP_PATH\" ]; then\n    printExitError \"Backup directory '$BACKUP_PATH' is not writable\"\nfi\n\ncd \"$PATH_TO_ESPO\"\n\nif [ ! -f \"data/config.php\" ]; then\n    printExitError \"The '$PATH_TO_ESPO' is not EspoCRM directory\"\nfi\n\nDB_NAME=$(php -r \"\\$config=include('data/config.php'); echo @\\$config['database']['dbname'];\")\nDB_USER=$(php -r \"\\$config=include('data/config.php'); echo @\\$config['database']['user'];\")\nDB_PASS=$(php -r \"\\$config=include('data/config.php'); echo @\\$config['database']['password'];\")\n\nif [ -z \"$DB_NAME\" ]; then\n    DB_NAME=$(php -r \"\\$config=include('data/config-internal.php'); echo @\\$config['database']['dbname'];\")\nfi\n\nif [ -z \"$DB_USER\" ]; then\n    DB_USER=$(php -r \"\\$config=include('data/config-internal.php'); echo @\\$config['database']['user'];\")\nfi\n\nif [ -z \"$DB_PASS\" ]; then\n    DB_PASS=$(php -r \"\\$config=include('data/config-internal.php'); echo @\\$config['database']['password'];\")\nfi\n\nif [ -z \"$DB_NAME\" ]; then\n    printExitError \"Unable to determine database name\"\nfi\n\nBACKUP_NAME=$(basename \"$PATH_TO_ESPO\")\nBACKUP_ARCHIVE_NAME=\"$(date +'%Y-%m-%d_%H%M%S').tar.gz\"\n\necho \">>> Backing up database ...\"\n\n# Detect database type and set appropriate dump command\nif command -v mariadb-dump &> /dev/null; then\n    DUMP_CMD=\"mariadb-dump\"\n    echo \">>> Detected MariaDB\"\nelif mysqldump --version 2>&1 | grep -qi \"mariadb\"; then\n    DUMP_CMD=\"mariadb-dump\"\n    echo \">>> Detected MariaDB\"\nelif command -v mysqldump &> /dev/null; then\n    DUMP_CMD=\"mysqldump\"\n    echo \">>> Detected MySQL\"\nelse\n    printExitError \"Neither MariaDB nor MySQL database found\"\nfi\n\ncd \"$BACKUP_PATH\" || {\n    printExitError \"Permission denied on $BACKUP_PATH\"\n}\n\nmkdir -p \"$BACKUP_NAME\"\ncd \"$BACKUP_NAME\"\n\n# --- Database backup ---\n\n\"$DUMP_CMD\" --user=\"$DB_USER\" --password=\"$DB_PASS\" \"$DB_NAME\" > \"db.sql\" || {\n    echo \"Enter database user:\"\n    read DB_USER\n\n    echo \"Enter database password:\"\n    read DB_PASS\n\n    \"$DUMP_CMD\" --user=\"$DB_USER\" --password=\"$DB_PASS\" \"$DB_NAME\" > \"db.sql\" || {\n        printExitError \"Unable to create a backup for the database '$DB_NAME'\"\n    }\n}\n\ntar -czf \"db.tar.gz\" \"db.sql\"\nrm \"db.sql\"\n\necho \">>> Database backup done.\"\n\n# --- Files backup ---\n\necho \">>> Backing up files...\"\n\ntar -czf \"files.tar.gz\" -C \"$PATH_TO_ESPO\" .\n\necho \">>> Files backup done.\"\n\n# --- Bundle into single archive ---\n\necho \">>> Creating final archive...\"\n\ncd ..\ntar czf \"$BACKUP_ARCHIVE_NAME\" \"$BACKUP_NAME\"/\n\n# Remove temporary files\nrm -rf \"$BACKUP_NAME\"\n\necho \"\"\necho \"Backup is created at '$BACKUP_PATH/$BACKUP_ARCHIVE_NAME'.\"\n"
  },
  {
    "path": "docs/administration/2fa.md",
    "content": "# 2-Factor Authentication\n\nEspoCRM supports the following 2-factor authentication methods: \n\n* TOTP (as of v5.7)\n* Email (as of v7.0)\n* SMS (as of v7.0)\n\nAn administrator needs to enable 2FA at Administration > Authentication and select allowed methods. Then users can enable 2FA for their accounts.\n\n## TOTP\n\n[Time-based One-time Password](https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm) is an algorithm that generates a one-time password which uses the current time as a source of uniqueness.\n\n\n!!! warning\n\n    The server time must be correct. Otherwise, authentication won't work.\n\n### Enabling for user\n\nYou need to have an authenticator application installed on your mobile phone (e.g. [Google Authenticator](https://en.wikipedia.org/wiki/Google_Authenticator)).\n\nGo to your user profile (from the menu at the top-right corner) and then click *Security* button. Then, enable 2FA, select the *TOTP* method. After that, scan the QR-code with your mobile application.\n\nNext time when you log in to Espo, you will need to enter your username and password, then enter a code from your mobile application.\n\n### If you lost your TOTP key\n\nIf you are not an administrator, you need to contact the administrator to ask them to disable 2FA for your user account.\n\nIf you are an administrator, the only option is to disable 2FA globally by setting `'auth2FA' => false` in the config file `data/config.php`.\n\n## Authentication via email\n\nWhen the Email 2FA is used, after a user entered a valid username and password, a code will be sent to their email address. Then, the user needs to enter that code to log in to Espo.\n\nIt's highly recommended for users to use a non-primary email address for 2FA. A user should have at least two email addresses (they can be added only by admin).\n\n### Enabling for user\n\nGo to your user profile (from the menu at the top-right corner) and then click *Security* button. Then, enable 2FA and select the *Email* method. Choose an email address (it's highly recommended to choose non-primary one) and then send a code. Then you will need to confirm the code.\n\n## Authentication via SMS\n\nRequires having an implementation for your SMS provider. An extension with SMS providers can be downloaded [here](https://github.com/espocrm/ext-sms-providers/releases).\n\n### Enabling for user\n\nGo to your user profile (from the menu at the top-right corner) and then click *Security* button. Then, enable 2FA and select the *SMS* method. Choose a phone number and then send a code. Then, you will need to confirm the code.\n"
  },
  {
    "path": "docs/administration/addresses.md",
    "content": "# Addresses\n\n## Countries\n\n*As of v8.3.*\n\nAn administrator can add country names with their ISO 3166-1 alpha-2 codes (at Administration > Address Countries).\nAdded countries will be available in autocompletion in Address fields. \nCountries marked as preferred will be displayed first (on empty input).\n\nCountries can also be [imported](import.md) from a CSV file.\n\nThe default predefined country list with English names can be optionally loaded. To do this, follow: Administration > Address Countries > top-right menu > Populate with default country list. \n"
  },
  {
    "path": "docs/administration/apache-server-configuration.md",
    "content": "# Apache server configuration for EspoCRM\n\nThese instructions are supplementary to the [server configuration](server-configuration.md) guidelines. Note that all configuration settings listed here are made on an Ubuntu server.\n\n## PHP requirements\n\nTo install all necessary libraries, run these commands in the terminal:\n\n```\nsudo apt-get update\nsudo apt-get install php-mysql php-json php-gd php-zip php-imap php-mbstring php-curl php-exif php-ldap php-xml\nsudo phpenmod imap mbstring\nsudo service apache2 restart\n```\n\n## Server configuration\n\nOn a **production** environment, the following configuration is recommended:\n\n* The document root should be set to `/path_to_espo/public/`.\n* An alias `/client/` => `/path_to_espo/client/` should be added.\n\nApache config example:\n\n```\nDocumentRoot /path_to_espo/public/\nAlias /client/ /path_to_espo/client/\n\n<Directory /var/www/html/>\n    AllowOverride None\n</Directory>\n\n<Directory /path_to_espo/public/>\n    AllowOverride All\n</Directory>\n```\n\nNote that `/path_to_espo` should be changed to the absolute path of the EspoCRM instance on your server. It can be `/var/www/html` if you extracted EspoCRM package to the default Apache root directory.\n\nThe location of the Apache config is usually `/etc/apache2/apache2.conf` (on Ubuntu) but can be different.\n\nYou need to have **mod_rewrite** enabled. You can do it by running in the terminal:\n\n```\nsudo a2enmod rewrite\nsudo service apache2 restart\n```\n\nFor **non-production environment** you can just set `AllowOverride All` for the root directory. Then the `.htaccess` file in the root directory will handle all rewrite rules.\n\n## Enabling rewrite rules\n\nEspoCRM requires *mod_rewrite* being enabled in Apache. W/o it you may encounter *'API Error: EspoCRM API is unavailable'* error during installation or see an information page prompting to configure your webserver.\n\nTo fix it, try the following steps **one by one**. After each step check if the issue is solved. If it works, then further steps are not needed.\n\n### 1. Enable *mod_rewrite* support for Apache\n\nTo enable *mod_rewrite*, run these commands in a terminal:\n\n```\nsudo a2enmod rewrite\nsudo service apache2 restart\n```\n\n### 2. Enable *.htaccess* support\n\nTo enable .htaccess support, add or edit the server configuration file. It can be:\n\n* `/etc/apache2/apache2.conf` \n* `/etc/httpd/conf/httpd.conf`\n* `/etc/apache2/sites-available/ESPO_VIRTUAL_HOST.conf`\n\nAdd the following code:\n\n```\n<Directory /PATH_TO_ESPO/>\n  AllowOverride All\n</Directory>\n```\n\nYou need to change `/PATH_TO_ESPO/` to the full path to your EspoCRM instance. It can be `/var/www/html/`.\n\nNote: On production, it's reasonable to use  `/PATH_TO_ESPO/public/` path instead.\n\nThen restart Apache:\n\n```\nsudo service apache2 restart\n```\n\n### 3. Add RewriteBase path (a last resort, not needed in most cases)\n\nOpen the file `/ESPOCRM_DIRECTORY/api/v1/.htaccess` and replace the following line:\n\n```\n# RewriteBase /\n```\n\nwith\n\n```\nRewriteBase /REQUEST_URI/api/v1/\n```\n\nwhere *REQUEST_URI* is a part of URL, e.g. for `https://example.com/espocrm/`, REQUEST_URI is *'espocrm'*.\n\n\n## Enable HTTP AUTHORIZATION support (only for FastCGI)\n\nFastCGI does not support HTTP AUTHORIZATION by default. If you use FastCGI, you have to enable it in your VirtualHost or `/etc/apache2/apache2.conf` (or httpd.conf) by adding the following code:\n\nFor Fcgid module:\n\n```\n<IfModule mod_fcgid.c>\n  FcgidPassHeader Authorization\n  FcgidPassHeader Proxy-Authorization\n  FcgidPassHeader HTTP_AUTHORIZATION\n</IfModule>\n```\n\nFor FastCgi module:\n\n```\n<IfModule mod_fastcgi.c>\n   FastCgiConfig -pass-header Authorization \\\n                 -pass-header Proxy-Authorization \\\n                 -pass-header HTTP_AUTHORIZATION\n</IfModule>\n```\n\nTo check which module is currently being used, run this command and find the module:\n\n```\napache2ctl -M\n```\n\n"
  },
  {
    "path": "docs/administration/api-before-save-script.md",
    "content": "# API Before-Save Script\n\n*As of v7.5.*\n\nA [formula](formula.md) script that is invoked on POST and PUT API requests to an entity endpoint before the record is saved.\nIt's executed only when the record is created or updated via the API (this also includes actions made through the UI as EspoCRM is a single page application – the frontend communicates with the backend via API). It's not executed when a record is saved from within the system (e.g. in hooks, workflow actions, custom code).\nCan be used for custom validation, duplicate checking and access control. Available at Administration > Entity Manager > {Entity type} > Formula.\n\n!!! warning\n\n    API Before-Save Script is not executed when doing mass update.\n\n    You can use `exception\\throwInvalid` [function](formula/exception.md#exceptionthrowinvalid) for additional internal\n    validation in the Before-save script. This script executes every time an entity is saved.\n\n!!! note\n\n    Avoid accessing related records in API Before-Save Script using a dot (e.g. `account.assignedUserId`). When the script is executed, the relation can be not yet established.\n\n## Special functions\n\n!!! warning\n\n    These functions are available only in *API Before-Save Script*. Using them in other places will produce an error.\n\nIn error throwing functions, the MESSAGE will be rendered in Espo in an error alert, it supports Markdown syntax. The BODY is an HTTP response body, which may be needed for integrations.\n\n### recordService\\skipDuplicateCheck\n\nReturns *true* if a *skipDuplicateCheck* HTTP header is passed (when a user is warned about a duplicate but opts to save the record anyway).\n\n!!! example\n\n    ```\n    if (!recordService\\skipDuplicateCheck()) {\n        // process duplicate checking\n    }\n    ```\n\n### recordService\\throwDuplicateConflict\n\n`recordService\\throwDuplicateConflict(RECORD_ID)`\n\n`recordService\\throwDuplicateConflict(RECORD_IDS)` – receives a list of IDs.\n\nThrows a duplicate conflict exception. This will show a modal dialog warning the user that the saved record\nmight be a duplicate.\n\n!!! example\n\n    ```\n    if (!recordService\\skipDuplicateCheck()) {\n        $id = record\\findOne('MyEntityType', null, null, 'name=', name);\n\n        if ($id) {\n            recordService\\throwDuplicateConflict($id);\n        }\n    }\n    ```\n\n### recordService\\throwBadRequest\n\n`recordService\\throwBadRequest(MESSAGE, [BODY])`\n\nThrows a Bad Request exception.\n\n!!! example\n\n    ```\n    recordService\\throwBadRequest('Invalid value.');\n    ```\n\n!!! example\n\n    ```\n    // HTTP response body.\n    $obj = object\\create();\n    $obk['key'] = 'value';\n  \n    recordService\\throwBadRequest('Invalid value.', $obj);\n    ```\n\n### recordService\\throwForbidden\n\n`recordService\\throwForbidden(MESSAGE, [BODY])`\n\nThrows a Forbidden exception.\n\n### recordService\\throwConflict\n\n`recordService\\throwConflict(MESSAGE, [BODY])`\n\nThrows a Conflict exception.\n\n## Examples\n\n### Duplicate checking\n\nExample 1:\n\n```\nif (entity\\isNew() && !recordService\\skipDuplicateCheck()) {\n    $id = record\\findOne('MyEntityType', null, null, 'name=', name);\n\n    if ($id) {\n        recordService\\throwDuplicateConflict($id);\n    }\n}\n```\n\nExample 2:\n\n```\nif (entity\\isNew() && !recordService\\skipDuplicateCheck()) {\n    $ids = list();\n\n    $id = record\\findOne('MyEntityType', null, null, 'name=', name);\n\n    if ($id) {\n        $ids = array\\push($ids, $id);\n    }\n\n    $id = record\\findOne('MyEntityType', null, null, 'emailAddress=', emailAddress);\n\n    if ($id) {\n        $ids = array\\push($ids, $id);\n    }\n\n    $ids = array\\unique($ids);\n\n    if (array\\length($ids)) {\n        recordService\\throwDuplicateConflict($ids);\n    }\n}\n```\n\n### Validation\n\nExample:\n\n```\nif (status == 'Completed' && !dateCompleted) {\n    recordService\\throwBadRequest(\"Missing `dateCompleted` value.\");\n}\n```\n\n### Access control\n\nExample:\n\n```\nif (\n    entity\\isAttributeChanged('status') &&\n    !array\\includes(env\\userAttribute('teamsIds'), '6133380f577a93492')\n) {\n    recordService\\throwForbidden(\"Not allowed to change status.\");\n}\n```\n"
  },
  {
    "path": "docs/administration/app-secrets.md",
    "content": "# App Secrets\n\n*As of v9.0.*\n\nApplications secrets allow you to securely store sensitive values in Espo, such as API keys and passwords. To access them, go to: Administration > App Secrets.\n\nSecrets are stored as instances of the *AppSecret* entity type. It's possible to read them from code and a Formula script.\n\n## Reading in Formula\n\n*As of v9.2.3.*\n\nExample:\n\n```\n$secretValue = ext\\appSecret\\get($secretName);\n```\n\n## Using in Workflows\n\nIn the *Send HTTP Request* action, it's possible to insert secrets into headers using the placeholder *{#secrets.name}*. Where *name* is the secret's name.\n"
  },
  {
    "path": "docs/administration/b2c.md",
    "content": "# Configuring EspoCRM for B2C (Business-to-Client)\n\nBy default, EspoCRM is configured for use in B2B business. It's possible to set it up solely for B2C.\n\n* Check *B2C Mode* at Administration > Settings.\n* Remove the *Account* tab from the navigation menu: Administration > User Interface.\n* Remove the *Account* fields from your layouts: Administration > Layout Manager.\n* Disable access to the *Account* scope in Roles if you allowed it before.\n* Remove the *Account* from picklists of all parent fields: Administration > Entity Manager > {Meeting/Call/Task/Email} > Fields > Parent.\n"
  },
  {
    "path": "docs/administration/backup-and-restore.md",
    "content": "# Backup and Restore\n\nThis article outlines backup and restore methods for EspoCRM in various environments:\n\n* [Non-containerized installation](#non-containerized-installation)\n* [Docker installation](#docker-installation)\n\n## Non-containerized installation\n\nRefers to a traditional installation that does not use containers.\n\n### Backup with a script\n\nYou can use a script to back up all needed data. Login via SSH and run the commands (tested on the Ubuntu server).\n\n#### Step 1. Download a script\n\n```bash\nwget https://raw.githubusercontent.com/espocrm/documentation/stable/docs/_static/scripts/backup.sh\n```\n\n#### Step 2. Run the script\n\n```bash\nbash ./backup.sh PATH_TO_ESPOCRM BACKUP_PATH\n```\n\nwhere\n\n * `PATH_TO_ESPOCRM` is a path to installed EspoCRM directory\n * `BACKUP_PATH` is a path to backup directory\n\nFor Ubuntu server it is:\n\n```bash\nbash ./backup.sh /var/www/html /opt/backups\n```\n\nNote: If your MariaDB / MySQL user doesn't have needed rights to dump your database, you will be prompted to enter credentials of another MariaDB / MySQL user.\n\nAfter successful creation, you will get a path to the created backup.\n\n### Manual backup\n\nTo make a full backup of your EspoCRM instance you need to copy EspoCRM files and dump the database. Here are the instructions on how to do it on an Ubuntu server with MySQL or MariaDB.\n\n#### Step 1. Back up files\n\nCreate an archive of the entire directory contents of the EspoCRM instance. You can use the following command:\n\n```bash\ntar -czf \"files.tar.gz\" -C /var/www/html .\n```\n\nThe command above implies that the path to your instance is `/var/www/html`, which is usual default path on Linux servers. Modify it if needed.\n\n#### Step 2. Back up database\n\nTo back up all your data, you have to know the database name and credentials for access. You can find the database name in the configuration file `/ESPOCRM_DIRECTORY/data/config-internal.php` under the section *database*. You can use this command to back up your database.\n\nFor MariaDB:\n\n```bash\nmariadb-dump --user=DATABASE_USER --password=DATABASE_PASSWORD DATABASE_NAME > \"db.sql\"\n```\n\nFor MySQL:\n\n```bash\nmysqldump --user=DATABASE_USER --password=DATABASE_PASSWORD DATABASE_NAME > \"db.sql\"\n```\n\n#### Step 3. Copy the backup\n\nThat's all. Now, you have to copy the created backup to a safe place.\n\n### Manual restore\n\nYou can restore the EspoCRM instance from the backup created as described above.\n\n#### Step 1. Unarchive backup files\n\nTo unarchive files, you can use *Archive Manager* or run the below command. Files need to be placed in the web-server directory.\n\n```bash\ntar -xzf \"files.tar.gz\" -C /var/www/html\n```\n\nwhere `/var/www/html` is the web-server directory.\n\n#### Step 2. Set required permissions\n\nThe files should be owned by the web-server user and have correct permissions. Set required permissions by following this [instruction](server-configuration.md#required-permissions-for-unix-based-systems).\n\n#### Step 3. Import database dump\n\nDatabase dump should be imported to the same database with the same user credentials, otherwise the correction should be made in the configuration file `ESPOCRM_DIRECTORY/data/config-internal.php`. To import your database from the dump, run the command below in a terminal:\n\nFor MariaDB:\n\n```bash\nmariadb --user=DATABASE_USER --password=DATABASE_PASSWORD DATABASE_NAME < db.sql\n```\n\nFor MySQL:\n\n```bash\nmysql --user=DATABASE_USER --password=DATABASE_PASSWORD DATABASE_NAME < db.sql\n```\n\n#### Step 4. Check/configure crontab\n\nCheck if your crontab is configured properly. Run the command below and check if a path to EspoCRM is correct:\n\n```bash\nsudo crontab -l -u www-data\n```\n\nwhere `www-data` is your web-server user.\n\nIf you have to make any changes, use this command:\n\n```bash\nsudo crontab -l -u www-data\n```\n\nMore details about configuring crontab see [here](server-configuration.md#setting-up-crontab).\n\n## Docker installation\n\n### Backup with a script\n\n!!! important\n\n    Script must be run from the host.\n\n#### Step 1. Download a script\n\n```bash\nwget https://raw.githubusercontent.com/espocrm/documentation/stable/docs/_static/scripts/backup-docker-container.sh\n```\n\n#### Step 2. Run the script\n\nRun one of the following commands at your choice:\n\n```bash\nsudo bash backup-docker-container.sh\n```\n\nor\n\n```bash\nsudo bash backup-docker-container.sh CONTAINER_NAME ./BACKUP_DIR\n```\n\n### Automatic backups\n\nBackups can be scheduled on the host by adding the following entry to the crontab:\n\n```\n0 1 * * * sudo bash /opt/scripts/backup-docker-container.sh CONTAINER_NAME /backup/espocrm >> /backup/espocrm/backup.log 2>&1\n```\n\n### Manual backup\n\nRun the following commands:\n\n```bash\nmkdir ./BACKUP_DIR\n\n# Database\nsudo docker exec CONTAINER_NAME mariadb-dump \\\n  -u DATABASE_USER --password=DATABASE_PASSWORD DATABASE_NAME \\\n  > ./BACKUP_DIR/db.sql\n\n# Files\nsudo docker exec CONTAINER_NAME tar czf - /var/www/html > ./BACKUP_DIR/files.tar.gz\n```\n\n### Manual restore\n\nRun the following commands:\n\n```bash\n# Database\nsudo docker exec -i CONTAINER_NAME mariadb \\\n  -u DATABASE_USER --password=DATABASE_PASSWORD DATABASE_NAME \\\n  < ./BACKUP_DIR/db.sql\n\n# Files\nsudo docker exec CONTAINER_NAME sh -c \"rm -rf /var/www/html/*\"\ncat ./BACKUP_DIR/files.tar.gz | sudo docker exec -i CONTAINER_NAME tar xzf - -C /\n\n# Restart\nsudo docker restart CONTAINER_NAME\n```\n"
  },
  {
    "path": "docs/administration/bpm-activities.md",
    "content": "# BPM Activities\n\nActivities encompass automated tasks, manual tasks, and sub-processes. On a flowchart, they are depicted as gray rectangles.\n\n* [Task](#task)\n* [Send Message Task](#send-message-task)\n* [User Task](#user-task)\n* [Script Task](#script-task)\n* [Sub-Process](#sub-process)\n* [Event Sub-Process](#event-sub-process)\n* [Call Activity](#call-activity)\n\n----\n\n## Task\n\nA task can execute different actions. Available actions are listed below.\n\nThe BPM task utilizes actions from the Workflow tool. The list of available actions is almost the same as in Workflows. See more details about [Workflow actions](workflows.md#actions).\n\n### Actions\n\n#### Create Record\n\nCreates a new record of a specific entity type.\n\n#### Create Related Record\n\nCreates a new record related to the target record.\n\n#### Update Target Record\n\nUpdates the target record. You can also utilize Formula script to set fields with calculated values.\n\nIt's possible to delete the record with the Formula expression: `deleted = 1`.\n\n#### Update Related Record\n\nUpdates a record (or multiple records) related to the target record. You can also utilize Formula script to set fields with calculated values.\n\n#### Update Created Record\n\nUpdates a record that was created within the current process.\n\nIt's possible to delete the record with the formula expression: `deleted = 1`.\n\n#### Update Process Record\n\nUpdates the process record. Can be used to assign the process to a specific user or team.\n\nIt's possible to delete the process record with the formula expression: `deleted = 1`.\n\n#### Link to Another Record\n\nRelates the target record with another record.\n\n#### Unlink from Another Record\n\nUnrelates the target record from another specified record.\n\n#### Apply Assignment Rule\n\nAssigns the record to a user based on a specific assignment rule. Can be applied to the target record, the process record, or any record created by the process. See [more](workflows.md#apply-assignment-rule).\n\n#### Create Notification\n\nCreates an in-app notification for specific users. See [more](workflows.md#create-notification).\n\nProcess variables can be included in a message with such placeholders: `{$$variable}`, where *$variable* is a variable defined in the process.\n\n#### Make Followed\n\nMakes specific users to follow the target record, the process record, or any record created by the process.\n\n#### Trigger Another Workflow Rule\n\nRuns a workflow rule of the sequential type. The target record of the called rule can be the same or be switched to a related record or a record created by the process.\n\n#### Run Service Action\n\nRuns a specific service action. The list of built-in actions is available [here](workflows.md#run-service-action). Developers can create custom service actions.\n\n#### Send HTTP Request\n\nCalls an external API endpoint. See [more](workflows.md#send-http-request).\n\n#### Execute Formula Script\n\nExecutes a specific Formula script.\n\n### Formula usage\n\nWhen using Formula in a task that creates or updates another record, the current entity (for the script) is switched the the record you are creating. To access attributes of the target record you can utilize the function `targetEntity\\attribute(ATTRIBUTE)`.\n\n!!! example\n\n    ```\n    // attribute of the target record\n    $someVariable1 = targetEntity\\attribute('name');\n\n    // attribute of the record you are creating or updating\n    $someVariable2 = name;\n\n    // attribute of the record you are creating or updating\n    $someVariable3 = entity\\attribute('name');\n    ```\n\n!!! warning\n\n    In the context of create and update record actions, it's recommended to use Formula only for setting attributes. Use the *Script Task* or *Execute Formula Script* action for any other logic.\n\nIf the parameter *Isolate Variables* is checked, Formula variables defined within the task won't be exposed outside of the task. The *Return Variables* parameter allows you to specify variables that will be exposed.\n\n!!! note\n\n    If you didn't check the *Isolate Variables* parameter, be aware that all variables defined in Execute Formula Script actions will remain available throughout the process and even after it finishes. Since some variables may contain sensitive data or consume disk space, checking the Isolate Variables parameter is recommended.   \n\n----\n\n## Send Message Task\n\nSends an email message to a specific recipient.\n\nAn email can be sent to:\n\n* User assigned to process\n* Target record (if such has email address)\n* Related record\n* Specific email address\n* Specific users\n* Specific teams\n* Specific contacts\n* Followers of target record\n\nYou can specify which email address the email will be sent from.\n\nIf you specify a *Reply-To* address, a sent email will contain it in the *Reply-To* header. It will facilitate a recipient to reply to that address instead of the address specified in the *From* field.\n\nWhen you use *Specific email address* option, it's possible to use process variables. E.g. `{$$emailAddress}`, where *$emailAddress* is a variable defined in the process before.\n\nAn Email Template is used to generate the email. You can use regular placeholders (both in body and subject) to substitute field values of the target record. You can also insert process variables (defined in a Script Task) in an email template with placeholders like `{$$variable}`.\n\nYou can catch a reply to a sent email with Message Intermediate Event further in the process.\n\nAdditional attachments can be added to an email using the *Attachments Variable* parameter. Specify a Formula variable name that contains an attachment ID or an array of attachment IDs. You can generate needed attachments in a Formula script in a previous action. As of v3.6.\n\n### Opting-out\n\nIt's possible to add opt-out link to an email body. Opting out can be caught within the process with Catching Signal Event with the signal name `optOut.ENTITY_TYPE.{$id}`, where *ENTITY_TYPE* should be replaced with an entity type (e.g. Lead), *{$id}* is a placeholder standing for the target record ID. Signal name usage example: `optOut.Lead.{$id}`.\n\n### Tracking URLs\n\nSee a [separate article](bpm-tracking-urls.md).\n\n----\n\n## User Task\n\nIt stops the flow until a user (specified explicitly or selected by an assignment rule) resolves the task. A Process User Task record will be created in the system. By default, there are 3 action types: Approve, Review, and Accomplish.\n\n* Approve – requires the user to choose between 'Approved' and 'Declined'.\n* Review – gives only one option: 'Reviewed'.\n* Accomplish – has two options: 'Completed' and 'Failed'.\n\nThe user assigned to the created Process User Task record will receive an in-app notification. An administrator can also enable email notifications for Process User Tasks under Administration > Notifications > Email Notifications.\n\nIt's possible to specify text with instructions for the user (markdown is supported).\n\nYou can use placeholders in *Name* and *Instructions* fields:\n\n* `{$attribute}` – attribute of target record\n* `{$$variable}` – process variable (defined by Script Task)\n\nUsers can also add the Process User Tasks dashlet on their dashboard to see their active process user tasks.\n\nAn administrator can add custom action types in Entity Manager. The resolution options available for a particular action type is controlled by dynamic logic. The logic can be edited as well.\n\n### Displaying on detail view\n\nIt's possible to display Process User Tasks on the detail view of the target entity.\n\n#### Using Report Panels\n\nYou can utilize the *Report Panels* feature to display process tasks on the record detail view. Create a Report of the List type that shows all Process User Tasks (no filters). Then, create a Report Panel (Administration > Report Panels) for the needed entity type with this list Report selected.\n\n#### Using created relationship\n\nIt's possible to create a Children-to-Parent relationship between some entity type and the Process User Task, then Process User Tasks will be available in the *Bottom* layout of that entity type. Go to Administration > Entity Manager > BpmnUserTask > Relationships > edit Children-to-Parent, check your entity type in *Foreign Fields*.\n\n### Resolution\n\nIt's possible to check a resolution of a passed Process User Task with diverging gateways or conditional events. This allows for making ramifications in the process flow depending on a resolution. The User Task resolution is available in conditions of gateways and conditional events.\n\nThe resolution (as well as any User Task field) can be also accessed further in the flow with Formula:\n\n```\n$resolution = bpm\\createdEntity\\attribute('USER_TASK_ELEMENT_ID', 'resolution');\n$resolutionNote = bpm\\createdEntity\\attribute('USER_TASK_ELEMENT_ID', 'resolutionNote');\n```\n\nThe element ID can be obtained from the User Task's detail view.\n\n### Canceling\n\nA created User Task can be canceled by a process. There are two ways:\n\n1. Using 'Update Created Record' action (within a Task activity), setting 'Is Canceled' field to 'true'.\n2. Using interrupting boundary event (attached to the User Task activity).\n\n![User Task](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/task-user.png)\n\n\n----\n\n## Script Task\n\nExecutes a [Formula](formula.md) script.\n\nYou can store some variables and use them further in the process. All variables you defined in the script will be automatically stored.\n\n```\n$myVar1 = 'test';\n$myVar2 = id;\n\n// ...\n\n$myVar2 = null;\n```\n\nVariables can be utilized in:\n\n* Condition checking\n* Tasks that create or update record\n* Email templates\n* Signal names\n* User Task names\n* Email addresses in a Send Message task\n\nYou can update the target record with a Script Task, though the more proper way is to use the Update Target Record action of a regular Task.\n\nWith the Script Task, you can define actions that are impossible to do with the regular Task. Examples:\n\n* Create a new user and send generated password ([see](formula-scripts-examples.md#creating-new-user))\n* Send email with generated PDF in attachment ([see](formula-scripts-examples.md#sending-email-with-generated-pdf-in-attachment))\n\nIf the parameter *Isolate Variables* is checked, Formula variables defined within the task won't be exposed outside of the task. The *Return Variables* parameter allows you to specify variables that will be exposed.\n\n!!! note\n\n    If you didn't check the *Isolate Variables* parameter, be aware that all defined variables will remain available throughout the process and even after it finishes. Since some variables may contain sensitive data or consume disk space, it might be reasonable to unset them at the end of the script.\n\n    ```\n    $tmpVariable = null;\n    ```\n\n    Though, checking the Isolate Variables parameter is recommended.\n\n----\n\n## Sub-Process\n\nA sub-process is an isolated process that executes within the parent process. A sub-process has it's own flowchart. It starts once the flow reaches its activity element in the parent process.\n\nA sub-process should have one (and only one) regular Start Event.\n\nA sub-process can be interrupted by an interrupting boundary event. When a sub-process is successfully ended (not interrupted and not ended with an error), the flow of the parent process proceeds to the next element.\n\nIt's possible to **pass a different target record** to a sub-process (to switch the target record to another). After you placed the Sub-Process element on a flowchart, click it to edit, then specify the target. It allows you to easily access fields of created records or records related to the target record. For example, to send a notification to the assigned user of the opportunity that was created within the process.\n\nIt's possible to define a target record using a Formula expression. You need to select the target *Record: {EntityType}* and specify a formula expression in the *Target ID Expression* field. The expression should evaluate to the ID of the record.\n\nWhen a sub-process is initiated, all formula **variables are copied** from the parent process to the sub-process. Variables of the sub-process are isolated from its parent process. You can specify which variables will be copied to the parent process upon the completion in the *Return Variables* parameter. Note: Specify variable names without a leading *$* character.\n\nWhen a sub-process is initiated, it receives an information about all records that have been created by the parent process by that moment. The sub-process can access those records. The parent process can access records created by the sub-process only after the sub-process is completed. Once the sub-process is completed, it passes the information about created records to the parent process.\n\n![Sub-Process](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/sub-process.png)\n\n### Multi-instance sub-process\n\n*As of v2.10.*\n\nThe *Collection Expression* should evaluate to a list of values. Each value will instantiate a separate sub-process. The value will be available in the variable `$inputItem`.\n\nIn case of a **sequential** multi-instance sub-process, sub processes will be executed one by one. Otherwise, they execute in parallel.\n\nIt's possible to have multiple sub-processes for different targets. By using the Formula function *record\\findRelatedMany*, it's possible to have sub-processes for related records. The result of the function is the list of IDs. You need to set the *Target ID Expression* to `$inputItem`.\n\nThe result of a multi-instance sub-process can be returned to a specific variable defined by the *Return Collection Variable* field. It will contain an array of objects. Each object will contain return-variables of each sub-process instance.\n\nWhen a multi-instance sub-process is interrupted by a boundary event, all other instances are cancelled.\n\nThe max number of sub-process instances is defined by the config parameter `bpmnSubProcessInstanceMaxCount`. The default value is `20`.\n\n----\n\n## Event Sub-Process\n\nAn Event Sub-Process has neither ingoing nor outgoing flows. It is triggered by its Start Event. The start event can be of any type: Conditional, Timer, Signal, Message, Error, Escalation.\n\nIt is possible to **pass a different target record** to an event sub-process. An event sub-process can *interrupt* its parent process. Whether the sub-process is interrupting is determined by the *Is Interrupting* parameter of its start event.\n\nWhen an event sub-process is initiated, all formula **variables are copied** from the parent process to the sub-process.\n\nWhen an event sub-process is initiated, it receives an information about all records that have been created by the parent process by that moment. The sub-process can access those records. Records created by the event sub-process won't be accessible by the parent process.\n\nNon-interrupting event sub-process can be executed **multiple times**. For example, when a condition occurred multiple times.\n\n![Event Sub-Process](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-sub-process.png)\n\n----\n\n## Call Activity\n\nExecutes a sub-process defined by a flowchart stored separately. Provides the ability to re-use the same flowchart in different processes. The Call Activity sub-process works the same way as a regular Sub-Process.\n\nIt is possible to pass a different target record to a sub-process.\n"
  },
  {
    "path": "docs/administration/bpm-compensation.md",
    "content": "# Compensation in BPM\n\n*As of Advanced Pack v2.14.*\n\nThe Compensation mechanism is supposed to perform undo actions when something went wrong. Only successfully completed activities can be compensated. Both tasks and sub-processes can be compensated.\n\nA compensation is initiated by triggering a Compensation Event (usually from an error handler). The throwing compensation event can specify an activity's ID that needs to be compensated. If the ID is omitted, all *visible* *compensable* activities will be compensated in the order reverse to their instantiation.\n\nBy utilizing intermediate throwing compensation events, it is possible to establish a specific order in which compensations will be executed.\n\n!!! note\n\n    Compensation can be applied only for activities that were successfully completed. A sub-process that is not yet finished cannot be compensated from outside.\n\nAn activity is **compensable** if one of the two following conditions is met:\n\n* Activity has a Boundary Compensation Event attached that is associated with a compensation activity.\n* Activity is a sub-process that contains a Compensation Event Sub-Process.\n\nBoundary compensation:\n\n![Compensation Intermediate Event (Boundary)](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-compensation-boundary.png)\n\nWhen a sub-process is compensated with the boundary event, the compensation activity does not have access to the sub-process internal state (called Black-Box compensation). To be able to access the internal state, use the Compensation Event Sub-Process inside the sub-process.\n\nWhen the parent process initiates compensation for the sub-process activity, if there's no boundary compensation event attached to that activity, it will check whether the sub-process contains an event sub-process with a compensation start event (called Compensation Handler). Then, it executes the compensation handler. The compensation handler usually is supposed to explicitly throw compensation events to compensate activities of the sub-process.\n\nCompensation event sub-process:\n\n![Compensation Start Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-compensation.png)\n\nAn activity is considered **visible** from the throwing Event when:\n\n* It is contained in a normal flow at the same level of the process/sub-process.\n* It is contained in the parent process/sub-process of an event sub-process in which the Event is contained.\n\nIn the same level:\n\n![Compensation End Event, same level](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-end-compensation-2.png)\n\nFrom the event sub-process:\n\n![Compensation End Event, event sub-process](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-end-compensation-1.png)\n\nCompensation events:\n\n* [Boundary](bpm-events.md#compensation-intermediate-event-boundary)\n* [Start](bpm-events.md#compensation-start-event) \n* [Intermediate throwing](bpm-events.md#compensation-intermediate-event-throwing)\n* [End](bpm-events.md#compensation-end-event)\n"
  },
  {
    "path": "docs/administration/bpm-configuration.md",
    "content": "# BPM Configuration\n\n## Deferring conditional event checking\n\n*As of v2.8.7.*\n\nWithin a period defined by the config parameter `bpmnPendingDeferPeriod` (`\"6 hours\"` by default), pending conditional event nodes are being checked as soon as possible.\nAfter that period, they will be checked with an interval defined by the parameter `bpmnPendingDeferIntervalPeriod` (`\"10 minutes\"` by default).\nThis is an optimization measure.\n\nIf an entity is updated, it will make nodes related to that entity to be checked one time regardless whether the defer period has been passed.\n\n## Pending event checking limit\n\nThe config parameter `bpmnProceedPendingMaxSize` (`20000` by default) limits max number of pending flows that can be processed. Consider increasing it if you usually have a large number of active processes.\n\n## Multi-instance sub-process limit\n\nThe max number of sub-process instances (within a multi-instance sub-process) is defined by the config parameter `bpmnSubProcessInstanceMaxCount`. The default value is `20`.\n\n## Running in parallel\n\n*As of v3.10.*\n\nCan be enabled by setting the config parameter `bpmnRunInParallel` to `true`. Running jobs [in parallel](jobs.md#running-jobs-in-parallel-processes) must be also enabled.\n\nFor scheduled processes, to process them in parallel, use a Timer Intermediate Event right after the Start Timer event. Scheduled processes are started sequentially even if the *bpmnRunInParallel* parameter is set to true.\n"
  },
  {
    "path": "docs/administration/bpm-drip-email-campaign.md",
    "content": "# Drip Email Campaign with BPM\n\nWith the [BPM tool](bpm.md) it's possible to create drip email campaigns.\n\n## Campaign starting\n\nThe drip email campaign for an individual target (lead or contact) will be represented as single BPM Process. A process can be started automatically or manually.\n\nYou need to create a *Process Flowchart* (under Administration > Flowcharts) and choose the *Lead* (or *Contact*) target type.\n\n### Starting on lead subscription\n\nA process instance will be started once a Lead enters into the CRM through the [Lead Capture](web-to-lead.md) form.\n\nYou need to use the *Signal Start Event* with a specific signal name. Put it on the flowchart layout and click it to edit. Specify the signal name with the value `@leadCapture.LEAD_CAPTURE_ID`, where *LEAD_CAPTURE_ID* is an ID of the lead capture record (can be obtained from its URL).\n\n### Starting once lead gets related with target list\n\nCan be useful if you don't utilize the Lead Capture but use some other logic. You need to do the same steps as in the previous section but use the signal name `@relate.targetLists.TARGET_LIST_ID`, where *TARGET_LIST_ID* is an ID of the target list record (can be obtained from its URL).\n\n### Starting manually\n\nEvery BPM process can be started manually (a user needs to have a corresponding permission granted with a role). You can use either the *Signal Start Event* or the regular *Start Event* in the flowchart.\n\n## Email sending\n\nUse multiple *[Send Message Tasks](bpm-activities.md#send-message-task)*. Each item will automatically send a specific email. You need to check *Opt-out link* parameter for these tasks to provide recipients with the ability to unsubscribe from the campaign.\n\nYou need to put *Timer Intermediate Events* between tasks and specify how much time should pass before every next email sending.\n\nYou also can use [Gateways](bpm-gateways.md) to diverge a flow upon certain conditions.\n\n## Handling opting-out\n\nOnce a target (recipient of an email) clicked on the unsubscribe link, the system broadcasts a signal `optOut.Lead.some-lead-id`, where *some-lead-id* is an actual ID of the lead record.\n\nWe want the whole process to be terminated once a Lead is opted out.\n\nFor this, you need to add the *Event Sub-Process*. Put a *Signal Start Event* inside the sub-process rectangle and specify the signal name with the value `optOut.Lead.{$id}`. You also need to check the parameter *Is Interrupting* for this event. By setting this parameter, we indicate that the whole parent process should be interrupted once the event is catched.\n\nHere, inside the sub-process, you can also add a *Task* that will do some manipulations with the target record (Lead).\n\n## Example\n\nYou can get a downloadable example [here](bpm-examples.md#downloadable-examples).\n\n![Example](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/drip-email-campaign.png)\n"
  },
  {
    "path": "docs/administration/bpm-events.md",
    "content": "# BPM Events\n\nEvents represent something that happens during a business process. They also start, end and interrupt a process flow. Depicted as a circle.\n\nEvents can be divided into the following groups:\n\n* Start – green circle. They are entry points of processes and sub-processes.\n* Intermediate – blue circle. Occur between start and end events in a process. Can throw or catch.\n* End – red circle. Define final points of process flows.\n* Boundary – blue circle attached to an activity. They allow to interact with running activities. Technically, they are intermediate catching events.\n\nAll available events:\n\n* Start Events\n  * [Start](#start-event)\n  * [Conditional](#conditional-start-event)\n  * [Timer](#timer-start-event)\n  * [Signal](#signal-start-event)\n  * [Error](#error-start-event)\n  * [Escalation](#escalation-start-event)\n  * [Compensation](#compensation-start-event)\n* Intermediate Events\n  * [Conditional (catching)](#conditional-intermediate-event-catching)\n  * [Timer (catching)](#timer-intermediate-event-catching)\n  * [Signal (catching)](#signal-intermediate-event-catching)\n  * [Signal (throwing)](#signal-intermediate-event-throwing)\n  * [Message (catching)](#message-intermediate-event-catching)\n  * [Escalation (throwing)](#escalation-intermediate-event-throwing)\n  * [Compensation (throwing)](#compensation-intermediate-event-throwing)\n* End Events\n  * [End](#end-event)\n  * [Terminate](#terminate-end-event)\n  * [Error](#error-end-event)\n  * [Escalation](#escalation-end-event)\n  * [Signal](#signal-end-event)\n  * [Compensation](#compensation-end-event)\n* Boundary Events\n  * [Error](#error-intermediate-event-boundary)\n  * [Conditional](#conditional-intermediate-event-boundary)\n  * [Timer](#timer-intermediate-event-boundary)\n  * [Escalation](#escalation-intermediate-event-boundary)\n  * [Signal](#signal-intermediate-event-boundary)\n  * [Message](#message-intermediate-event-boundary)\n  * [Compensation](#compensation-intermediate-event-boundary)\n\n----\n\n## Start Events\n\n### Start Event\n\nDoesn't have parameters. It's a starting point of the process. A Start Event can be initiated manually by a user who has access to create processes. This can be done either from the processes list view or from the detail view of a target record.\n\n![Start Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-1.png)\n\nCan be also used as an entry point of a sub-process.\n\n![Start Event in sub-process](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-2.png)\n\n### Conditional Start Event\n\nA starting point of a process. It's supposed to be triggered automatically when specified conditions are met. There are three types of triggers: 'After record created', 'After record updated', and 'After record saved'. Event conditions are defined in the same way as conditions in the Workflows tool. See [here](workflows.md#conditions).\n\n![Conditional Start Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-conditional-1.png)\n\nCan be also used to start an event sub-process.\n\n![Conditional Start Event for event sub-process](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-conditional-2.png)\n\n!!! note\n\n    When used to start an event sub-process, the Boundary Start Event is not synced with the flow. Condition checking is run in idle which may cause some delay. A flowchart design should not rely on a condition event being checked immediately.\n\n### Timer Start Event\n\nA starting point of a process. It initiates processes by scheduling. You need to select a list report (which returns records, each one will initiate a separate process) and specify execution scheduling (in the crontab notation).\n\n![Timer Start Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-timer-1.png)\n\nCan be also used to start an event sub-process. In this case, it is scheduled to be triggered at time defined by event parameters.\n\n![Timer Start Event for event sub-process](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-timer-2.png)\n\n### Signal Start Event\n\nCan be used to start processes and event sub-processes.\n\nWhen it's used to start a process, only *object signals* can be used.\n\nWhen it's used to start an event sub-process, it's possible to use placeholders in a signal name. Example: `test.{$id}`, {$id} will be replaced with the ID of the target record. \n\n!!! note\n\n    Signals are not limited by a process scope. Signal triggered in one BPM process can be caught in another process.\n\n!!! note\n\n    Signal name cannot be empty.\n\n![Signal Start Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-signal.png)\n\nSee [more info](bpm-signals.md) about signals.\n\n### Error Start Event\n\nCan only be used to start an event sub-process. It's triggered once an error event is thrown within the same process.\n\nIf the *Error Code* is specified, the event will be triggered only when an error with the same code occurs. If the *Error Code* is empty, it will catch any error.\n\nIt cannot be non-interrupting, because the process gets terminated once an error event is thrown.\n\n![Error Start Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-error.png)\n\nIt's possible to view an error code and message in the flow log.\n\nThe error code and the exception message can be obtained further in the flow with Formula functions `bpm\\caughtErrorCode` and `bpm\\caughtErrorMessage`.\n\n!!! note\n\n    When an error event sub-process is defined inside a regular sub-process, it can be reasonable to re-throw the error in the end\n    of the event sub-process with the Error End Event. It will propagate the error to the top level.\n\n### Escalation Start Event\n\nCan be used only to start an event sub-process. It's triggered once an escalation event it thrown within the same process.\n\nIf the Escalation Code is specified, it will be triggered only when an escalation with the same code occurs. If the Escalation Code is empty, it will catch any escalation.\n\n![Escalation Start Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-escalation.png)\n\n### Compensation Start Event\n\n*As of v2.14.*\n\nStarts a sub-process compensation handler. Can be used only in an event sub-process.\n\nWhen the parent process initiates compensation for the sub-process activity, if there's no boundary compensation event attached to that activity, it will check whether the sub-process contains an event sub-process with a compensation start event (called Compensation Handler). Then, it executes the compensation handler. The compensation handler usually is supposed to explicitly throw compensation events to compensate activities of the sub-process.\n\n![Compensation Start Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-start-compensation.png)\n\n!!! note\n\n    Actual only when the event sub-process is inside a regular sub-process.\n    \nIn case of a multi-instance sub-process, the compensation handler is processed for each completed instance of the sub-process.\n\n----\n\n## Intermediate Events\n\n### Conditional Intermediate Event (Catching)\n\nThis event stops the flow until specified criteria is met. Event conditions are defined in the same way as conditions in the Workflow tool. See [here](workflows.md#conditions). Note that BPM tool introduces [additional functions](bpm-formula.md) that can be used in a Formula script.\n\n![Conditional Intermediate Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-conditional.png)\n\n### Timer Intermediate Event (Catching)\n\nThis event stops the flow and waits as long as it's determined by event's parameters.\n\nFor more complex timer settings you can utilize a [Formula](formula.md) script. Formula scripts should return a Date-Time value (date-time string in the UTC timezone). Once this time arrives, the flow is proceeded to the next element.\n\nBy utilizing *datetime\\closest* Formula function, it's possible to set the timer to a specific time in the future, e.g. the beginning of the next working day.\n\n![Timer Intermediate Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-timer.png)\n\n### Signal Intermediate Event (Catching)\n\nStops the flow until a specific signal is catched. Placeholders can be used in a signal name.\n\n!!! note\n\n    Signal name can not be empty.\n\nSee [more info](bpm-signals.md) about signals.\n\n### Signal Intermediate Event (Throwing)\n\nBroadcasts a specified signal. Placeholders can be used in a signal name. Example: `test.{$id}`, {$id} will be replaced with the ID of the target record.\n\nIf the first character of a signal name is `@`, it will broadcast an object signal along with the current target record. This signal type can be used only to initiate a new process or trigger a workflow rule.\n\n![Signal Intermediate Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-signal-throw.png)\n\n!!! note\n\n    Signals are not limited by a process scope. Signal triggered in one BPM process can be caught in another process.\n\n!!! note\n\n    Signal name can not be empty.\n\nSee [more info](bpm-signals.md) about signals.\n\n### Message Intermediate Event (Catching)\n\nStops the flow until an email is received.\n\nOnly emails sent not by internal users can trigger the event.\n\nIt's possible to utilize the event in pair with the *Send Message* task. The event will wait until the sent email is replied. Specify that email in the *Replied To* parameter.\n\nThe *Related To* parameter requires that the email was related (via the Parent field) to a specific record.\n\nThere is the ability to specify Formula conditions that the email should satisfy to trigger the event. You can utilize it to skip auto-response emails or to catch emails containing a specific ID. Formula example: `string\\contains(body, $id)`.\n\n![Message Intermediate Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-message.png)\n\n### Escalation Intermediate Event (Throwing)\n\nThrows an escalation. The Escalation Code can be specified. An escalation can be catched by a boundary event (if it's thrown within a sub-process) or by an event sub-process.\n\n![Escalation Intermediate Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-escalation.png)\n\n### Compensation Intermediate Event (Throwing)\n\n*As of v2.14.*\n\nBehaves the same as the [compensation end event](#compensation-end-event) with the only difference that it continues flow execution to the next element.\n\nCan be useful to ensure processing of multiple compensations in a specific order.\n\n![Compensation Intermediate Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-compensation.png)\n\n----\n\n## End Events\n\n### End Event\n\nEnds the current flow. It doesn't end flows running in parallel. When the flow reaches an end event and there isn't anything running in parallel, then the process ends.\n\n![End Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-end.png)\n\n### Terminate End Event\n\nEnds all flows. The process is subsequently ended.\n\n![Terminate End Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-end-terminate.png)\n\n### Error End Event\n\nTerminates the process and triggers an error. The Error Code can be specified. The error can be catched by a boundary event (if it's thrown within a sub-process) or by an event sub-process.\n\n![Error End Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-end-error.png)\n\n!!! note\n\n    Uncaught errors are propagated to the parent process.\n\n### Escalation End Event\n\nEnds the flow and triggers an escalation. The Escalation Code can be specified. The escalation can be catched by a boundary event (if it's thrown within a sub-process) or by an event sub-process.\n\n![Escalation End Event](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-end-escalation.png)\n\n### Signal End Event\n\nEnds the flow and broadcasts a specified signal.\n\nPlaceholders can be used in a signal name. Example: `test.{$id}`, {$id} will be replaced with the ID of the target record.\n\nIf the first character of the signal name is `@`, it will broadcast an object signal along with the current target record. This signal type can be used only to initiate a new process or trigger a workflow rule.\n\n!!! note\n\n    Signals are not limited by a process scope. A signal triggered in one BPM process can be caught in another process.\n\n!!! note\n\n    Signal name can not be empty.\n\nSee [more info](bpm-signals.md) about signals.\n\n### Compensation End Event\n\n*As of v2.14.*\n\nInitiates compensation and ends the flow once compensation is completed.\n\nCan compensate a specific activity (by specifying an activity's ID, the activity ID can be obtained on the detail view of the activity) or all activities (that are visible from the event). Only completed activities (not failed or interrupted) are compensated.\n\nAn activity is considered visible from the throwing Event when:\n\n* It is contained in normal flow at the same level of the process/sub-process.\n* It is contained in the parent process/sub-process of an event sub-process in which the Event is contained.\n\nIn the same level:\n\n![Compensation End Event, same level](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-end-compensation-2.png)\n\nFrom the event sub-process:\n\n![Compensation End Event, event sub-process](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-end-compensation-1.png)\n\nWhen the activity ID is omitted, all visible completed activities are compensated in the order reverse to their instantiation.\n\nCompensation is supposed to perform undo actions when something went wrong. Usually, compensation is triggered from error handlers.\n\n----\n\n## Boundary Events\n\nBoundary events can be attached to activities (usually sub-processes). Boundary event can interrupt an activity (if the *Is Interrupting* parameter is checked). Non-interrupting boundary event can be triggered multiple times.\n\n### Error Intermediate Event (Boundary)\n\nIt's triggered once an error event is thrown within the activity (sub-process) it's attached to.\n\nIt cannot be non-interrupting, because the activity gets terminated once an error event is thrown.\n\nIf the Error Code is specified, it will be triggered only when an error with the same code occurs. If the Error Code is empty, it will catch any error.\n\n![Error Intermediate Event (Boundary)](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-end-error.png)\n\nIt's possible to view the error code and the exception message in the flow log.\n\nThe error code and the exception message can be obtained further in the flow with Formula functions `bpm\\caughtErrorCode` and `bpm\\caughtErrorMessage`.\n\n!!! note\n\n    If the error event is attached to a task with the *Send HTTP Request* action, it's possible to catch a specific response error code (e.g. 404, 403).\n\n\n### Conditional Intermediate Event (Boundary)\n\nTriggered when specific conditions are met. Note that same non-interrupting events can be triggered multiple times. First, when conditions get fulfilled, then, when conditions get unfulfilled, and so on.\n\n![Conditional Intermediate Event (Boundary)](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-conditional-boundary.png)\n\n!!! note \n\n    The Boundary Conditional Event is not synced with the flow. Condition checking is run in idle which may cause some delay. A flowchart design should not rely on a boundary condition event being checked immediately.\n\n### Timer Intermediate Event (Boundary)\n\nTriggered after a specific period of time. The timer starts once the activity starts.\n\n![Timer Intermediate Event (Boundary)](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-timer-boundary.png)\n\n\n### Escalation Intermediate Event (Boundary)\n\nIt's triggered once an escalation event is thrown within the activity (sub-process) it's attached to.\n\nIf the Escalation Code is specified, it will be triggered only when an escalation with the same code occurs. If the Escalation Code is empty, it will catch any escalation.\n\n![Escalation Intermediate Event (Boundary)](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-escalation.png)\n\n\n### Signal Intermediate Event (Boundary)\n\nIt's triggered once a specific signal is broadcasted. Note that a signal can be triggered from anywhere in the system, not necessarily from the same process.\n\nPlaceholders can be used in a signal name. E.g. `test.{$id}`, {$id} will be replaced with the target's ID.\n\n![Signal Intermediate Event (Boundary)](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-signal-boundary.png)\n\n### Message Intermediate Event (Boundary)\n\nTriggered once an email is received. It functions the same as *Message Intermediate Event (Catching)*.\n\n### Compensation Intermediate Event (Boundary)\n\n*As of v2.14.*\n\nTriggered once compensation is initiated for an activity it is attached to. Must be connected with a compensation activity (task or sub-process).\n\n![Compensation Intermediate Event (Boundary)](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/event-intermediate-compensation-boundary.png)\n\n!!! note\n\n    Compensation can be applied only for activities that were successfully completed.\n\nWhen it's a sub-process being compensated, the compensation activity does not have access to the sub-process internal state (called Black-Box compensation). To be able to access the internal state, use the compensation event sub-process inside the sub-process instead.\n\nIn case of a multi-instance sub-process, the compensation activity is processed for each completed instance of the sub-process.\n\n"
  },
  {
    "path": "docs/administration/bpm-examples.md",
    "content": "# BPM Examples\n\n## Downloadable examples\n\nYou can download the CSV file with examples and then import it into your EspoCRM instance.\n\n1. Download the [CSV file](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/csv/bpm-examples.csv) with examples.\n2. In your EspoCRM, go to Administration > Import, select *Process Flowchart* entity type and upload the CSV file. Go through import steps.\n3. You will find imported examples under Administration > Flowcharts.\n\n!!! note\n\n    These flowcharts are not active, so they won't run until you set them active.\n\nIncluded examples:\n\n* User task\n* Drip email campaign\n* Tracking URLs\n* Sub-process\n* Email reply catching\n\n## Screenshot-only examples\n\n#### Example 1\n\n![Example 1](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/example-1.png)\n\n#### Example 2\n\n![Example 2](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/example-2.png)\n\n#### Example 3\n\n![Example 3](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/example-3.png)\n\n#### Example 4\n\n![Example 4](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/example-4.png)\n"
  },
  {
    "path": "docs/administration/bpm-formula.md",
    "content": "# BPM Formula Functions\n\nThe [BPM tool](bpm.md) provides additional formula functions.\n\nA Formula script can be utilized in conditions, script tasks, and various task actions. Some functions can be used in a workflow (broadcastSignal, startProcess).\n\n* [bpm\\targetEntity\\attribute](#bpmtargetentityattribute)\n* [bpm\\createdEntity\\attribute](#bpmcreatedentityattribute)\n* [bpm\\processEntity\\attribute](#bpmprocessentityattribute)\n* [bpm\\startProcess](#bpmstartprocess)\n* [bpm\\broadcastSignal](#bpmbroadcastsignal)\n* [bpm\\caughtErrorCode](#bpmcaughterrorcode)\n* [bpm\\caughtErrorMessage](#bpmcaughterrormessage)\n\n### bpm\\targetEntity\\attribute\n\n`bpm\\targetEntity\\attribute(ATTRIBUTE)`\n\nFetches an attribute value of a target record.\n\n### bpm\\createdEntity\\attribute\n\n`bpm\\createdEntity\\attribute(ALIAS_ID, ATTRIBUTE)`\n\nFetches an attribute value of a record created within a process. \n\nAvailable records:\n\n* records created within *Task* activities;\n* user tasks;\n* sent messages.\n\nALIAS_ID can be obtained:\n\n* from the detail view of a *Task* that has an action that creates a record;\n* from the detail view of a *User Task* (ID field);\n* from the detail view of a *Send Message Task* (ID field).\n\n!!! example\n\n    ```\n    $resolutionNote = bpm\\createdEntity\\attribute('e6cmwnd894', 'resolutionNote');\n    ```\n\n### bpm\\processEntity\\attribute\n\n`bpm\\processEntity\\attribute(ATTRIBUTE)`\n\nFetches an attribute value of a process record.\n\n### bpm\\startProcess\n\n`bpm\\startProcess(FLOWCHART_ID, TARGET_TYPE, TARGET_ID, [ELEMENT_ID])`\n\nStarts a process.\n\n!!! example\n\n    `bpm\\startProcess('flowchart-id', 'Account', 'account-id');`\n\n### bpm\\broadcastSignal\n\n* `bpm\\broadcastSignal(SIGNAL_NAME)` – broadcast a regular signal\n* `bpm\\broadcastSignal(SIGNAL_NAME, ENTITY_TYPE, ENTITY_ID)` – broadcast an object signal\n\nIt can be useful to broadcast a custom signal from a workflow rule and then catch it inside a running process. A workflow rule will perform some condition checking and only after that will broadcast the signal.\n\n!!! example \"Example, regular signal\"\n\n    ```\n    $signalName = string\\concatenate(\n        'notePostedInCaseBySupportManager.',\n        entity\\attribute('id')\n    );\n\n    bpm\\broadcastSignal($signalName);\n    ```\n\n    Then it will be possible to catch the signal in a BPM process by listening to the signal `notePostedInCaseBySupportManager.{$id}`.\n\n!!! example \"Example, object signal\"\n\n    Workflow on Quote Item broadcasts a signal when amount is changed.\n\n    ```\n    bpm\\broadcastSignal('@quoteItemIsChanged', 'Quote', entity\\attribute('quoteId'));\n    ```\n\n    Then it will be possible to catch the signal by a workflow. It can be useful for situations when you need to recalculate something when a related record is changed.\n    \n    \n### bpm\\caughtErrorCode\n\n*As of v2.14.*\n\nReturns the code of a caught error. Error codes are of the string type. Can be used after a catching Error Event.\n\n### bpm\\caughtErrorMessage\n\n*As of v2.14.*\n\nReturns the message of a caught exception. Can be used after a catching Error Event.\n"
  },
  {
    "path": "docs/administration/bpm-gateways.md",
    "content": "# BPM Gateways\n\nGateways diverge and converge flows. Depicted as a yellow diamond. They can be used to determine a path in which the flow will go depending on specific conditions. They can split a flow into multiple parallel flows and join parallel flows into a single one.\n\n* [Exclusive](#exclusive-gateway)\n* [Inclusive](#inclusive-gateway)\n* [Parallel](#parallel-gateway)\n* [Event Based](#event-based-gateway)\n\n----\n\n## Exclusive Gateway\n\nCan diverge or converge flows.\n\nIn case of diverging, it defines a single flow (path) that will be chosen according specified criteria. The first met condition determines the flow, next conditions are omitted. There is the ability to specify a default flow. The default flow will be chosen if there are no conditions met. The default flow is marked with a slash sign.\n\n!!! important\n\n    There must be at least two outgoing flows to be able to specify diverging criteria.\n\nIn case of converging, it just directs the flow to the outgoing element. It does not block the flow, hence parallel flows won't be merged into a single flow.\n\n![exclusive gateway divergent](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/gateway-exclusive-divergent.png)\n\n![exclusive gateway convergent](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/gateway-exclusive-convergent.png)\n\n----\n\n## Inclusive Gateway\n\nCan diverge or converge flows.\n\nIn case of diverging, it can direct to one or multiple parallel flows (paths), depending on accomplishment of criteria of each flow. The default flow is chosen if there are no met conditions. The default flow is marked with a slash sign.\n\n!!! important\n\n    There must be at least two outgoing flows to be able to specify diverging criteria.\n\nIf there is a necessity to merge parallel flows produced by a diverging inclusive gateway, you need to use a converging inclusive gateway. It will wait for all incoming flows and only then will continue to the outgoing element.\n\n![inclusive gateway](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/gateway-inclusive.png)\n\n!!! note\n\n    Diverging and converging gateways must be balanced. The number of flows outgoing from a diverging gateway should equal the number of flows incoming to a converging gateway. If between these gateways one of flows splits into nested parallel flows, these nested flows must be converged before the outer converging gateway. And so on.\n\n!!! note\n\n    If one of parallel flows has been ended for some reason, then the diverging converging will never be processed. The process will be blocked. Avoid the flowchart design that can bring about such a situation.\n\n----\n\n## Parallel Gateway\n\nCan diverge or converge flows.\n\nIn case of diverging, it splits the flow into multiple parallel flows. There are no parameters for this gateway type.\n\nIn case of converging, it waits until all incoming flows come and only then continues to the next outgoing element.\n\n![parallel gateway](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/gateway-parallel.png)\n\n!!! note\n\n    Diverging and converging gateways must be balanced. The number of flows outgoing from a diverging gateway should equal the number of flows incoming to a converging gateway. If between these gateways one of flows splits into nested parallel flows, these nested flows must be converged before the outer converging gateway. And so on.\n\n!!! note\n\n    If one of parallel flows has been ended for some reason, then diverging gateway will never be processed. The process will be blocked. Avoid the flowchart design that can bring about such a situation.\n\n----\n\n## Event Based Gateway\n\nCan only diverge flows.\n\nIt stops the flow until any of outgoing events gets triggered. The triggered event determines the single flow. Other outgoing events get rejected.\n\nOnly intermediate events can be on the other end of outgoing sequence flows.\n\n![event based gateway](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/gateway-event-based.png)\n"
  },
  {
    "path": "docs/administration/bpm-signals.md",
    "content": "# Signals\n\nSignals are events with a specific name. Signals are broadcasted globally, they are not limited by a process scope. It means that a signal triggered in one BPM process can be caught in another process.\n\nThe signals feature is a part of the Advanced Pack extension and can be utilized in the BPM and Workflows tools.\n\nHow signals are broadcasted:\n\n* There are set of standard signals which are broadcasted upon specific events in the application. These *built-in signals* are listed below in the article.\n* It's possible to broadcast [custom signals](bpm-events.md#signal-intermediate-event-throwing) in a BPM process.\n* It's possible to broadcast custom signals using the [Formula function](bpm-formula.md#bpmbroadcastsignal) `bpm\\broadcastSignal(SIGNAL_NAME)`.\n* It's possible to broadcast custom signals via PHP code.\n\nThere are two types of signals:\n\n* Regular signals\n* Object signals\n\nIn this article:\n\n* [Regular signals](#regular-signals)\n* [Object signals](#object-signals)\n* [Naming clarification](#naming-clarification)\n\n## Regular signals\n\n* Can be broadcasted and caught within a running process.\n* Cannot be used to start a process or a workflow rule.\n\nIn BPM processes, the *Signal Intermediate Events* can catch and throw only regular signals.\n\n### Built-in signals\n\nBelow is the list of available out-of-the-box signals which are broadcasted in the system upon specific conditions.\n\n!!! note\n\n    Signal name parts written in the upper case (e.g. ENTITY_TYPE, ID, LINK_NAME) must be replaced with corresponding values. E.g. when an Account with an ID `abc01` is updated, a signal `update.Account.abc01` is broadcasted. See the naming clarification below.\n\n#### Default\n\n* `create.ENTITY_TYPE` – record of ENTITY_TYPE created, e.g. `create.Lead`;\n* `update.ENTITY_TYPE.ID` – record update, e.g. `update.Lead.aabbcc01`;\n* `delete.ENTITY_TYPE.ID` – record removed;\n* `relate.ENTITY_TYPE.ID.LINK_NAME` – record related with another record (only for *many-to-many*);\n* `relate.ENTITY_TYPE.ID.LINK_NAME.FOREIGN_ID` – record related with another record, ID of the related record is specified (only for *many-to-many*);\n* `unrelate.ENTITY_TYPE.ID.LINK_NAME` – record unrelated from another record (only for *many-to-many*);\n* `unrelate.ENTITY_TYPE.ID.LINK_NAME.FOREIGN_ID` – (only for *many-to-many*);\n* `createRelated.ENTITY_TYPE.ID.LINK_NAME` – created a related record, one-to-many relationship, e.g. Opportunity created for Account;\n* `createChild.ENTITY_TYPE.ID.CHILD_ENTITY_TYPE` – when created a record related through a parent, e.g. Meeting created for Account;\n* `streamPost.ENTITY_TYPE.ID` – when somebody posted in the stream;\n\n#### Contacts/Leads\n\n* `leadCapture.ENTITY_TYPE.ID` – when a Lead (or Contact) is processed through the Lead Capture (confirmed opt-in if the double opt-in is enabled);\n* `leadCapture.ENTITY_TYPE.ID.LEAD_CAPTURE_ID` – the same, but the ID of a Lead Capture record is specified;\n* `optOut.ENTITY_TYPE.ID` – person opted-out;\n* `optOut.ENTITY_TYPE.ID.TARGET_LIST_ID` – person opted-out from a specific target list;\n* `cancelOptOut.ENTITY_TYPE.ID` – person opted-in again;\n* `cancelOptOut.ENTITY_TYPE.ID.TARGET_LIST_ID`;\n* `eventAccepted.ENTITY_TYPE.ID.EVENT_ENTITY_TYPE` – person accepted a meeting/call invitation;\n* `eventAccepted.ENTITY_TYPE.ID.EVENT_ENTITY_TYPE.EVENT_ID` – person accepted a meeting/call invitation, event id is specified;\n* `eventTentative.ENTITY_TYPE.ID.EVENT_ENTITY_TYPE` – person set Tentative status in a meeting/call invitation;\n* `eventTentative.ENTITY_TYPE.ID.EVENT_ENTITY_TYPE.EVENT_ID`;\n* `eventAcceptedTentative.ENTITY_TYPE.ID.EVENT_ENTITY_TYPE` – person set Accepted or Tentative status in a meeting/call invitation;\n* `eventAcceptedTentative.ENTITY_TYPE.ID.EVENT_ENTITY_TYPE.EVENT_ID`;\n* `eventDeclined.ENTITY_TYPE.ID.EVENT_ENTITY_TYPE` – person declined a meeting/call invitation;\n* `eventDeclined.ENTITY_TYPE.ID.EVENT_ENTITY_TYPE.EVENT_ID`\n\n#### Contacts/Leads/Accounts/Users\n\n* `clickUrl.ENTITY_TYPE.ID` – recipient opened a tracking URL , see [here](bpm-tracking-urls.md);\n* `clickUrl.ENTITY_TYPE.ID.CAMPAIGN_TRACKING_URL_ID` – recipient opened a specific tracking URL;\n\n#### Other\n\n* `clickUniqueUrl.UNIQUE_ID` – recipient opened a tracking URL with a unique ID, see [here](bpm-tracking-urls.md);\n\n### Placeholders\n\nWhen defining a signal name in Signal Events in a BPM Flowchart, you can use placeholders:\n\n* `{$attribute}` – attribute of target record\n* `{$$variable}` – formula variable\n\nE.g. `mySignal.{$status}.{$id}` – *status* and *id* are attributes of the target record. Placeholders will be replaced with attribute values, so the actual signal name will look like `mySignal.New.someIdValue`.\n\n## Object signals\n\n* Broadcasted along with the entity (record).\n* Prefixed with `@` character.\n* Can be used only to initiate a new process or workflow rule.\n* Can't be caught within a running process.\n* Can be broadcasted by a running process. \n\n!!! note\n\n    Signal Intermediate Event (Catching) can't catch object signals. \n\nExample: A process triggers signal *@approve*. A target record of the *Lead* entity type is attached to the signal. You have another BPM flowchart for the *Lead* entity type that starts with the *@approve* signal. In this case, a new process will be started, and the Lead record from the first process will be passed as a target record of the second process. \n\n### Built-in signals\n\nBelow is the list of available out-of-the-box signals that are broadcasted in the system.\n\n!!! note\n\n    Signal name parts written in the upper case (e.g LINK_NAME, FOREIGN_ID) must be replaced with corresponding values. See the naming clarification below.\n\n#### Default\n\n* `@create` – record created;\n* `@update` – record updated;\n* `@delete` – record removed (can't be used in BPM);\n* `@relate.LINK_NAME` – record related with another record (only for *many-to-many*); the foreign ID is passed in the `id` parameter;\n* `@relate.LINK_NAME.FOREIGN_ID` – record related with another record, an ID of related record is specified (only for *many-to-many*);\n* `@unrelate.LINK_NAME` – record unrelated from another record; the foreign ID is passed in the `id` parameter;\n* `@unrelate.LINK_NAME.FOREIGN_ID`\n\n#### Contacts/Leads:\n\n* `@leadCapture` – when a Lead (or Contact) is processed through the Lead Capture (confirmed opt-in if it's enabled);\n* `@leadCapture.LEAD_CAPTURE_ID`\n* `@optOut` – person opted-out;\n* `@optOut.TARGET_LIST_ID` – person opted-out from a specific target list;\n* `@cancelOptOut` – person opted-in again;\n* `@cancelOptOut.TARGET_LIST_ID`\n\n#### Contacts/Leads/Accounts/Users\n\n* `@clickUrl` – recipient opened a tracking URL;\n* `@clickUrl.CAMPAIGN_TRACKING_URL_ID` – recipient opened a specific tracking URL;\n\n#### Meetings/Calls/Events\n\n* `@eventAccepted.ENTITY_TYPE` – an attendee accepted the event (ENTITY_TYPE can be *Contact*, *Lead*, *User*; as of v3.0.13); the foreign ID is passed in the `id` parameter;\n* `@eventTentative.ENTITY_TYPE` – an attendee set a tentative acceptance status; the foreign ID is passed in the `id` parameter;\n* `@eventDeclined.ENTITY_TYPE` – an attendee declined the event; the foreign ID is passed in the `id` parameter;\n* `@eventAcceptedTentative.ENTITY_TYPE` – an attendee accepted the event or set as tentative (ENTITY_TYPE can be *Contact*, *Lead*, *User*; as of v3.0.13); the foreign ID is passed in the `id` parameter;\n\n### Signal parameters\n\n*As of v3.2.*\n\nSome object signal are passed with additional parameters. These parameters can be accessed with a formula function `workflow\\\\signalParam('parameterName')`.\n\n## Naming clarification\n\n* *ID* – an ID of a record that you can obtain from the browser address bar;\n* *ENTITY_TYPE* – an entity type of the record (not translated), you can obtain it at Administration > Entity Manager;\n* *LINK_NAME* – a relation name, you can obtain it at Administration > Entity Manager;\n* *FOREIGN_ID* – an ID of a related record.\n"
  },
  {
    "path": "docs/administration/bpm-tips.md",
    "content": "# BPM Tips\n\n## Execution in idle\n\nWhen a process is initiated by a user interaction (e.g. after record is created), it starts to execute in the web server\nprocess until the flow reaches a catching event, *Send Message Task*, or *User Task*, which will switch execution to the idle mode (process will continue\nto run by cron/daemon). \n\nIf you have script tasks that take some time to run, it's reasonable to force to switch execution to the idle mode.\nThis will prevent a user from waiting until scripts are finished. In worst cases it can even cause a timeout error. The trick is to add *Timer Intermediate Event* with 0 timer value. You can add it right after a start event.\n\n## Unsetting process variables\n\nVariables defined in a *Script Task* and *Execute Formula Script* action will be stored in the Process (unless *Isolate Variables* is checked). If you don't need a specific variable to be used further in the process, it's reasonable to unset it in the end of the script.\n\n```\n$tempVariable = null;\n```\n\nAlso consider to unset sensitive data immediately after usage.\n\n## Cleaning up ended processes\n\nEnded Processes are *not* cleaned up automatically, as they may hold information important for the business. You may utilize a scheduled Workflow rule that will handle removal of ended Processes.\n\n## Self-removal\n\nYou can set up a BPM process to remove itself. Add *Task* > *Update Process Record*. Add in Formula: `deleted = true;`.\n\n## Displaying processes on record detail view\n\nYou can utilize the [Report Panels](../user-guide/reports.md#report-panels) feature to display all related processes on the record detail view.\n\n1. Create a List report for the Process entity type with the *Target* runtime filter.\n2. Create a report panel (Administration > Report Panels) for your entity type, select the report.\n"
  },
  {
    "path": "docs/administration/bpm-tracking-urls.md",
    "content": "# Tracking URLs with BPM\n\n## Non-unique URL\n\nIt's possible to add links into email body and catch when a recipient clicked on it. It provides the ability to automate interactions with customers.\n\nA Tracking URL can be created at Campaigns > top-right menu > Tracking URLs. Create a URL and obtain the generated placeholder (example: `{trackingUrl:5d8206aa9d76df4c8}`). Use that placeholder as a URL of the link in your email template.\n\nFurther in the process flow, you will be able to catch the URL click with the *Signal Intermediate Event (Catching)*.\n\nWhen the tracking URL is clicked, the system broadcasts the signal `clickUrl.ENTITY_TYPE.ID.TRACKING_URL_ID`. Where *ENTITY_TYPE* is an entity type of the person stored in the CRM, *ID* is a record ID of the person, *TRACKING_URL_ID* is an ID of the tracking URL record. See the example below.\n\nProcess flowchart example:\n\n![BPM Tracking URL](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/bpm/tracking-urls.png)\n\nIn this example, the target entity type is *Lead*.\n\nThe signal name, defined in the catching event: `clickUrl.Lead.{$id}.5d8206aa9d76df4c8`, where `5d8206aa9d76df4c8` is an ID of the *Tracking URL* (can be obtained from the address bar). You need to replace *5d8206aa9d76df4c8* with your ID. `{$id}` is a placeholder that will be automatically replaced with the ID of the Lead.\n\n### Example\n\nYou can get a downloadable example [here](bpm-examples.md#downloadable-examples).\n\n## Unique URL\n\n*Available as of Advanced Pack 2.7.0 and EspoCRM 6.1.3.*\n\nUseful when the URL must be unique for a specific process. E.g. send an email for a feedback on provided customer support, the email contains unique links to rate quality of support.\n\nThe signal  `clickUniqueUrl.UNIQUE_ID` will be broadcasted when the URL is opened by a recipient, where *UNIQUE_ID* is a generated ID.\n\nUse code `{trackingUrl:TRACKING_URL_ID.{$$variableName}}` in an email template instead of a *URL:* , where *variableName* is a name of the variable where the generated ID is stored, *TRACKING_URL_ID* is an ID of the Tracking URL record (can be obtained from the address bar). The code will be automatically substituted with a proper URL when the email is sent.\n\nSteps:\n\n1\\. Create Tracking URL at Campaigns > top-right menu > Tracking URLs.\n\n\n2\\. In BPM: Use an *Execute Formula Script* action or *Script Task* to generate a unique and store it in a variable:\n\n```\n$uniqueId = util\\generateId();\n```\n\n3\\. In BPM: Add a *Send Message* task. Use an email template with the link `{trackingUrl:TRACKING_URL_ID.{$$uniqueId}}`. Replace `TRACKING_URL_ID` with the ID of the *Tracking URL* record. This link is supposed to be clicked by a recipient.\n\n4\\. In BPM: Use a *Signal Catching* event with the signal `clickUniqueUrl.{$$uniqueId}`.\n"
  },
  {
    "path": "docs/administration/bpm.md",
    "content": "---\nsearch:\n  boost: 2\ntags:\n  - automation\n  - bpm\n---\n\n# Business Process Management\n\nThe Business Process Management (BPM) tool provides the ability to model and automate business processes in EspoCRM in a no-code/low-code way. The engine executes business processes described in the BPMN 2.0 standard.\n\nThe BPM tool is available in [Advanced Pack](https://www.espocrm.com/extensions/advanced-pack/) extension.\n\n![BPM example](../_static/images/administration/bpm/bpm-1.png)\n\n### Difference from Workflows tool\n\nThe Workflows tool is intended for automation of simple business rules, without sequential flow items, when there is no need to display the flow graphically.\n\nThe BPM tool is intended for more complex business logic, where there can be diverging and converging flows, execution delays, user interactions. The flowchart view makes the business process more comprehensible for a human, the log allows you to see how the process was held.\n\nThe BPM tool has all the capabilities of the Workflows tool. If you've used the Workflows tool before, your knowledge will be useful for getting into BPM, as they share a number of features.\n\nIn this article:\n\n* [Process Flowcharts](#process-flowcharts)\n* [Processes](#processes)\n* [Flowchart Elements](#flowchart-elements)\n* [Conditions](#conditions)\n\n## See also\n\n* [Examples](bpm-examples.md)\n* [Signals](bpm-signals.md)\n* [Compensation](bpm-compensation.md)\n* [BPM specific formula functions](bpm-formula.md)\n* [Drip email campaign with BPM](bpm-drip-email-campaign.md)\n* [Tracking URLs with BPM](bpm-tracking-urls.md)\n* [Tips](bpm-tips.md)\n* [Configuration](bpm-configuration.md)\n* [Quick tour](https://app.supademo.com/demo/cmflay16uf28039ozjxxlw5sn)\n\n## Process Flowcharts\n\nAvailable under Administration > Flowcharts. An administrator can also add the Process Flowcharts tab to the navigation bar.\n\nFlowcharts are intended for modeling business processes. An administrator can create and edit flowcharts. Regular users can only view flowcharts.\n\nEvery Flowchart has its specific entity type (defined by the *Target Type* field). The Flowchart determines execution of future process instances. It comprises flowchart elements and connections between elements.\n\nIf a Process Flowchart has the unchecked *Is Active* field, then it won't initiate process instances.\n\nTo show details and parameters of a certain flowchart element you need to click on it. In the edit mode you will be able to edit parameters.\n\n## Processes\n\nAvailable under Administration > Processes. An administrator can also add the Processes tab to the navigation bar.\n\nA Process represents a business process instance. When it's initiated, it gets the status *Started*. When the Process is finished, it gets the status *Ended*. \n\nA Process is executed according to its Flowchart. The Flowchart of a Process can't be changed after the Process is started.\n\nA Process is obligatorily related to a single target record.\n\nProcesses can be started:\n\n* Automatically – Upon specific conditions, signal, or scheduling, described in the Flowchart.\n* Manually – To start process manually, a user needs to click the *Start Process* button on the Processes list view, or on the record detail view from the dropdown in the top-right corner.\n* By a Workflow rule – using the *Start BPM Process* action in a rule. It allows you to pass the workflow's target record or a related record as a target for the new process.\n\nBy using a Workflow with the manual trigger, it's possible to have a button on the detail view that will start a particular process.\n\nThe execution of a Process is visualized with colors highlighting statuses of flow nodes:\n\n* green – processed;\n* yellow – pending;\n* violet – in process;\n* gray – failed.\n\n![Process execution](../_static/images/administration/bpm/process-execution.png)\n\n**Only one Process** for the same target record and Flowchart can be active at the same time. It means that if you have multiple Start Events, once one of them is triggered (the process is started), other Start Events will be ignored while the Process is active. \n\nUsually Processes start their execution flow from a Start Event (green colored circle). One Process Flowchart can have multiple Start Events.\n\n### Manipulating\n\nA Process can be **stopped manually** by a user who has edit access to that Process. You can do it from the dropdown menu next to the *Edit* button.\n\nIt's possible to **manually reject or interrupt** pending and active flow nodes. You can do it from the *Log* panel on the Process detail view in the dropdown menu of a specific Flow Node. Note that in some cases after rejecting a Flow Node the Process becomes suspended and won't ever end by itself. You will need to either manually stop it or start a flow from any node to continue executing.\n\nIt's possible to **manually start a flow from any element** of an already started Process. You need to click on a specific flowchart element on the Process detail view and then click the button *Start flow from here*.\n\nEnded, stopped and interrupted Processes can be *reactivated* (from the dropdown next to the *Edit* button). After reactivation, the Process does not have any active Flow Nodes. You need to manually start the flow from a specific Flow Node element. Ended Sub-Processes can be reactivated only if their parent Process is active. Meaning that you might need to reactivate the parent Process first.\n\n### Access control\n\nOnly administrators can create or edit Flowcharts. With Roles it's possible to allow regular users to view Flowcharts, and view or edit Processes. Note that a user needs also to have access to the Process Flowchart scope to be able to view Process Flowchart details. \n\n## Flowchart Elements\n\nSee more detail in separate articles:\n\n* [Gateways](bpm-gateways.md)\n* [Events](bpm-events.md)\n* [Activities](bpm-activities.md)\n\n### Gateways\n\nGateways diverge and converge flows. Depicted as a yellow diamond. They can be used to determine a path in which the flow will go depending on specific conditions. They can split the flow into multiple parallel flows and join parallel flows into a single one.\n\n### Events\n\nEvents represent something that happens during a business process. They also start, end and interrupt the process flow. Depicted as a circle.\n\n### Activities\n\nAutomated tasks, manual tasks and sub-processes. Represented as a gray rectangle.\n\n### Flows\n\n#### Sequence Flow\n\nRepresented as a solid arrow. It indicates the order in which process elements will be executed.\n\n## Conditions\n\nConditional events, exclusive and inclusive diverging gateways have conditions that determine the flow of the process.\n\nThrough the UI, there is the ability to check conditions for the following records:\n\n* Target record;\n* Records related to the target through many-to-one and children-to-parent relationships;\n* Records created by the Process via tasks;\n* User Task records, what allows checking a task resolution.\n\nIt's also possible to define conditions with [Formula](formula.md) expressions. Example: `status == 'New' && assignedUserId == null`. \n\nConditions in the BPM tool are the same as in the Workflow tool. See more details about [workflow's conditions](workflows.md#conditions).\n"
  },
  {
    "path": "docs/administration/collaborators.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Collaborators\n\n*As of v9.0.*\n\nThe Collaborators feature allow multiple users to work on the same record.\nUsers added as collaborators to a record can view the record, can read the stream and post to the stream.\n\nThe Collaborators feature is available for custom entities created via the Entity Manager and\nfor the following out-of-the-box entity types: Task, Case, Account, Contact, Lead, Opportunity, Document, Knowledge Base Article and Target List.\n\n\n## Enabling\n\nThe Collaborators feature can be enabled for an entity type in the Entity Manager at:\nAdministration > Entity Manager > {Entity Type} > Edit > Collaborators.\n\nOnce the Collaborators feature is enabled for an entity type:\n\n* Link-multiple field *Collaborators* is automatically created.\n* Bool filter *Shared* is added.\n\nThe administrator needs to add the created *Collaborators* field to the layout. It's recommended to add to the side panel\nunder the Teams field: Administration > Entity Manager > {Entity Type} > Layouts > Side Panel Fields.\n\n## Behavior\n\nAssignees are automatically added to collaborators. This ensures that when a record is reassigned to another user,\nthe previous assignee remains a collaborator unless explicitly removed.\n\nA user who creates a record is automatically pre-filled as a collaborator.\nThis ensures that a user with 'own' read access will still have access to a record after assigning it to another user.\n\n## Access\n\nUsers added as collaborators to a record obtain *read* and *stream* access, provided their access level, as defined by Roles, is other than *no*.\n\nAccess prerequisites:\n\n* Assignment Permission is required to be able to add a user to collaborators.\n* Edit access to a record is required to be able to add collaborators.\n\nLimitations:\n\n* Portal users cannot be added as collaborators.\n\n"
  },
  {
    "path": "docs/administration/commands.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Console Commands\n\n!!! note\n\n    You can run `php command.php` instead of `bin/command`. May be reasonable if there's no execute permission for *bin/command*. To grant execute permission, run `chmod +x bin/command`.\n\n!!! note\n\n    On Unix-based systems, it is reasonable to run commands under the root (or web server) user.\n\n## List of available commands\n\n```\nbin/command\n```\n\n## Clear cache\n\n```\nphp clear_cache.php\n```\n\n## Rebuild\n\n```\nphp rebuild.php\n```\n\nClears cache, rebuilds database and other things.\n\n### Hard rebuild\n\n*As of v7.4.*\n\n```\nbin/command rebuild --hard\n```\n\nHard database rebuild. It will drop unused columns, decrease exceeding column lengths, fix index names, set proper collations. It won't drop unused tables (consider removing them manually).\n\nIf a parameter `-y` is specified, it won't prompt for confirmation before running hard rebuild (as of v9.0).\n\nRecommended to have a database backup before running hard rebuild.\n\n## Changing user password\n\n```\nbin/command set-password [username]\n```\n\nWhere `[username]` is a user name, e.g. `admin`.\n\n## Upgrade\n\n```\nbin/command upgrade\n```\n\nUpgrades EspoCRM instance to the next available version. The upgrade package is downloaded automatically. It may take a few steps to upgrade to the latest version, so you will need to run the same command multiple times.\n\nSee additional parameters [here](upgrading.md#additional-parameters).\n\n## Extension\n\nInstalling or upgrading:\n\n```\nbin/command extension --file=\"path/to/extension/package.zip\"\n```\n\nUninstalling:\n\n```\nbin/command extension -u --name=\"Extension Name\"\n```\n\nUninstalling by ID:\n\n```\nbin/command extension -u --id=\"extension-ID\"\n```\n\nList all extensions:\n\n```\nbin/command extension -l\n```\n\n## Running job\n\n```\nbin/command run-job JobName\n```\n\nWhere *JobName* is an internal name of the job you want to run.\n\n!!! example\n\n    ```\n    bin/command run-job Cleanup\n    bin/command run-job ProcessMassEmail\n    ```\n\n## Version\n\nPrint the current version:\n\n```\nbin/command version\n```\n\n## Setting user password\n\n```\nbin/command set-password {username}\n```\n\nWhere `{username}` is a user name, e.g. `admin`.\n\n## Creating admin user\n\n*As of v7.4.*\n\n```\nbin/command create-admin-user {username}\n```\n\nWhere `{username}` is a user name, e.g. `admin`.\n\nCan be useful when you need to run an Espo instance from a repository without the need to go through UI installation.\n\n## Import\n\nSee more detail [here](import.md#console-commands).\n\n## App info\n\n```\nbin/command app-info\n```\n\nWith this command you can get some information about the application (container services, binding, jobs).\n\n## Update app timestamp\n\n*As of v8.1.*\n\n```\nbin/command update-app-timestamp\n```\n\nUpdates the app timestamp to the current time. When an Espo instance is updated or an extension is installed or uninstalled, the app timestamp is updated to let the browser know that the old cache is not actual anymore. Sometimes developers may need to update the app timestamp manually, for example, when writing custom JavaScript code.\n\n## Rebuild category paths\n\n```\nbin/command rebuild-category-paths {EntityType}\n```\n\nRebuilds category paths. For example, for DocumentFolder, WorkflowCategory. May be needed if for some reason paths data is corrupted resulting in not working expanded mode.\n\n## Config get\n\n*As of v10.0.*\n\nPrint a config parameter value:\n\n```\nbin/command config:get {param}\n```\n\nPrint in JSON:\n\n```\nbin/command config:get {param} --json\n```\n\nNote: In the examples, `{param}` is a placeholder, curly braces should not be used.\n\n## Config set\n\n*As of v10.0.*\n\n\nSet a value (implies string type):\n\n```\nbin/command config:set {param} {value}\n```\n\nSet with type:\n\n```\nbin/command config:set {param} true --type=bool\n```\n\nSupported types: `string`, `bool`, `int`, `float`, `json`. If the type is not specified, the input value is treated as string. Always specify the type if the stored parameter value must be anything other than string.\n\nSet a value passed in JSON:\n\n```\nbin/command config:set {param} [\\\"one\\\", \\\"two\\\"] --type=json\n```\n\nSet a nested parameter:\n\n```\nbin/command config:set database.host localhost\n```\n\nNote: In the examples, `{param}` and `{value}` are placeholders, curly braces should not be used.\n"
  },
  {
    "path": "docs/administration/config-params.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Config parameters\n\nConfig parameters can be changed or added manually in the file `data/config.php`. Parameters can also be added to the file `data/config-internal.php`. Use the **internal config** to store sensitive parameters.\n\nIn this article:\n\n* [List of parameters](#list-of-parameters)\n* [Config files](#config-files)\n\n## List of parameters\n\nThe list of parameters along with their default values. This is not a full list of params. Most of params available in the admin UI are not listed here.\n\n* [General](#general)\n* [UI](#ui)\n* [Access control](#access-control)\n* [Notifications](#notifications)\n* [Emails](#emails)\n* [Stream](#stream)\n* [Clean-up](#clean-up)\n* [Passwords](#passwords)\n* [Auth](#auth)\n* [Security](#security)\n* [Jobs & Daemon](#jobs-daemon)\n* [Mass Email](#mass-email)\n* [Kanban](#kanban)\n* [Text search](#text-search)\n* [PDF](#pdf)\n* [Events](#events)\n* [Attachments](#attachments)\n* [Misc](#misc)\n\n### General\n\n* siteUrl – URL of EspoCRM instance;\n* useCache – `true`;\n* isDeveloperMode – `false` – enables developer mode; not to be used on instances installed from a package; only for an instance that is run right from a repository;\n* useCacheInDeveloperMode – `false` – to use front-end cache in developer mode; front-end is not cached by default in developer mode;\n* maintenanceMode – `false` – only administrators will have access to the system;\n* disableCron – `false`;\n* useWebSocket – `false`;\n* ajaxTimeout – `60000` – timeout for ajax requests (in milliseconds);\n* language – system language;\n* timeZone – system timezone;\n* exportDelimiter – `','` – default export delimiter;\n* recordListMaxSizeLimit – `200` – max number of records can be fetched in a single GET API request;\n* maxSelectTextAttributeLengthForList – `10000` – text fields are cut when records accessed with a list request;\n* displayListViewRecordCount – `true` – to display a number of records on the list view;\n* addressCountryList – array of countries available in autocomplete;\n* addressCityList – array of cities available in autocomplete;\n* addressStateList – array of states available in autocomplete;\n* defaultCurrency – currency applied by default;\n* baseCurrency – which currency to use as base when defining rates;\n* currencyList – array of available currencies;\n* thumbImageCacheDisabled – `false` – to disable thumb image files being created in `data/upload/thumbs` directory (as of v7.0);\n* globalSearchMaxSize – `10` – how much records is shown in the global search;\n* massActionIdleCountThreshold – `100` – record number threshold after which mass-action is processed in idle (as of v7.1);\n* exportIdleCountThreshold  – `1000` – record number threshold after which export is processed in idle (as of v7.1);\n* leadCaptureAllowOrigin –  `*` – *Access-Control-Allow-Origin* response header value for the lead capture endpoint;\n* ipAddressServerParam – `REMOTE_ADDR` – server parameter to be used for obtaining a request IP address (as of v7.5);\n\n### UI\n\n* applicationDescription – the text in the meta tag; default value: `EspoCRM – Open Source CRM application` (as of v7.0);\n* adminPanelIframeDisabled – `false` – disables the right iframe-panel on the administration page (as of v7.0);\n* activitiesCreateButtonMaxCount – `3` – a max number of create buttons to display on the Activities page (as of v7.2);\n* listViewSettingsDisabled – `false` – disable list view settings (as of v8.1);\n* tabQuickSearch – `true` – tab quick search in the navbar (as of v8.5);\n\n### Access control\n\n* aclAllowDeleteCreated – `true` – whether to allow regular users to delete record they created, even they don't have *delete* access to;\n* aclAllowDeleteCreatedThresholdPeriod – `24 hours` – time window available for deletion of created records;\n\n### Notifications\n\n* adminNotifications – `true` – notifications in admin panel;\n* adminNotificationsNewVersion – `true` – notifications about new versions in admin panel;\n* adminNotificationsNewExtensionVersion – `true` – notifications about new extension versions in admin panel;\n* emailReminderPortionSize – `10` – how much email reminders can be sent at once (as of v7.0);\n* notificationsMaxSize – `5` – how much in-app notifications is shown when the notification panel is shown up;\n* notificationsCheckInterval – `10` – an interval between checks for new notifications (actual only if web socket is not enabled); \n* popupNotificationsCheckInterval – `15` – an interval between checks for new popup notifications (actual only if web socket is not enabled) (as of v7.3.2);\n* reminderMaxCount – `10` – a max number of reminders per event (as of v8.3);\n* notificationGrouping – `true` – notification grouping (as of v9.2);\n\n### Emails\n\n* emailKeepParentTeamsEntityList – `['Case']` – when a related email is fetched, teams of the parent record will be copied to the email; by default, it's available only for cases;\n* emailForceUseExternalClient – `false` – when composing an email, all users will be forced to use external client;\n* emailAutoReplySuppressPeriod – `'2 hours'` – an auto-reply email (for group email account) won't be sent to the same recipient if one was already sent in a period of time defined by the parameter; to prevent looping (as of v6.1.8);\n* emailAutoReplyLimit – `5` – a max number of auto-reply emails that can be sent to one recipient within a period defined by the *emailAutoReplySuppressPeriod* parameter (as of v7.0);\n* emailFoldersDisabled – `false` – disables email folders;\n* emailRecipientAddressMaxCount – `100` – max number of addresses allowed in TO, CC, BCC (as of v7.5);\n* emailTemplateHtmlizerDisabled – `false` – disables Handlebars template engine for email templates;\n* emailServerAllowedAddressList – the list of allowed internal addresses in the format *host:port*, e.g. `localhost:587` (as of v9.3.2);\n\n### Stream\n\n* noteEditThresholdPeriod – `'7 days'` – how much time is available for editing stream posts;\n* noteDeleteThresholdPeriod – `'1 month'` – how much time is available for deleting stream posts;\n* streamEmailWithContentEntityTypeList – `['Case']` – to display the content of the email in stream; by default, it's available only for cases;\n* recordFollowersLoadLimit – `6` – how much records loaded in the *Followers* field;\n* notePinnedMaxCount – `5` – max number of pinned notes per record;\n* streamReactionsCheckMaxSize – `50` – when refreshing a user's stream, how many posts will be checked for new reactions; as of 9.0;\n\n### Clean-up\n\n* cleanupJobPeriod – `'10 days'` – cleaning up deleted Job records;\n* cleanupActionHistoryPeriod – `'15 days'` – action history records;\n* cleanupAuthTokenPeriod – `'1 month'` – auth tokens;\n* cleanupAuthLogPeriod – `'2 months'` – auth log;\n* cleanupAppLog – `true` – app log cleanup (as of v9.1);\n* cleanupAppLogPeriod – `'30 days'` – app log cleanup period (as of v8.3);\n* cleanupNotificationsPeriod – `'2 months'` – notifications;\n* cleanupAttachmentsPeriod – `'15 days'` – attachments with roles 'Export File', 'Mail Merge', 'Mass Pdf' and attachments relate for deleted records;\n* cleanupOrphanAttachments – `false` – cleaning up attachments that were uploaded but not linked with any record; *cleanupAttachmentsPeriod* is used; an experimental parameter;\n* cleanupBackupPeriod – `'2 months'` – backup of files created during upgrades;\n* cleanupDeletedRecordsPeriod – `'2 months'` – complete deletion of records that were marked as deleted (*deleted = 1*);\n* cleanupSubscribers – `true` – cleaning up stream subscribers for not-actual records (as of v7.3);\n* cleanupSubscribersPeriod – `'2 months'` – period for cleaning up subscribers for not-actual records (as of v7.3);\n* cleanupAudit – `true` – to perform cleanup of the audit log;\n* cleanupAuditPeriod – `3 month` – how long audit log records stay before cleanup;\n\n### Passwords\n\n* passwordStrengthLength – min password length;\n* passwordStrengthLetterCount – how many letters are required for passwords;\n* passwordStrengthNumberCount – how many numbers are required for passwords;\n* passwordStrengthBothCases – `false` – password must contain letters of both upper and lower case;\n* passwordRecoveryRequestLifetime – `3 hours` – how long a password recovery link is valid;\n* passwordChangeRequestNewUserLifetime – `2 days` – how long a password change link for new users is valid (as of v7.1);\n* passwordChangeRequestExistingUserLifetime – `2 days` – how long a password change link (initiated by admin) for existing users is valid (as of v7.1);\n\n### Auth\n\n* authAnotherUserDisabled – `false` – disable the ability to log in as another user for admins (as of v7.3);\n* authLogDisabled – `false` – disable auth log records (as of v7.4);\n* authApiUserLogDisabled – `false` – disable auth log records for successful connections of API users (as of v7.4);\n* auth2FAEmailCodeLifetimePeriod – `'10 minutes'` – lifetime of email 2FA codes;\n* auth2FASmsCodeLifetimePeriod – `'10 minutes'` – lifetime of SMS 2FA codes;\n\n#### Brute force prevention for IP address\n\n* authMaxFailedAttemptNumber – `10` – if the number of failed login attempts within a specific period exceeds the specified number, then the system won't allow to login; \n* authFailedAttemptsPeriod – `'60 seconds'` – period taken into account;\n* authFailedCodeAttemptsPeriod – `'5 minutes'` – period for checking a number of failed 2FA code check attempts (as of v8.4);\n\n#### Brute force prevention for user name\n\n*As of v9.3.*\n\n* authUsernameFailedAttemptsLimitEnabled – `false` – enables brute force prevention measure delays;\n* authMaxUsernameFailedAttemptNumber – `30` – if the number of failed login attempts within a specific period exceeds the specified number, then the system will do a delay;\n* authUsernameFailedAttemptsPeriod – `'60 seconds'` – period taken into account;\n* authUsernameFailedAttemptsDelay – `2` – delay in seconds;\n\n### Security\n\n* adminUpgradeDisabled – `false` – disables the ability to upgrade or upload extensions via the UI; (as of v8.1);\n* clientSecurityHeadersDisabled – `false` – disable security headers (as of v7.2);\n* clientCspDisabled –  `false` – disable Content-Security-Policy header for the client page (as of v7.2);\n* clientCspScriptSourceList – a script source white-list for the Content-Security-Policy header (as of v7.2);\n* clientStrictTransportSecurityHeaderDisabled –  `false` – disables `Strict-Transport-Security` header, actual if a webserver adds it (as of v7.3);\n* clientCspFormActionDisabled –  `false` – disables addition of `form-action 'self'` in the CSP header (as of v9.0.8);\n\n### Jobs & Daemon\n\n* jobMaxPortion – `15` – max number of jobs per one execution; a portion of jobs that is run in a queue is counted as one job;\n* jobPeriod – `7800` – max execution time (in seconds) allocated for a single job; if exceeded then set to *Failed*;\n* jobPeriodForActiveProcess – `36000` – max execution time (in seconds) allocated for a single job with active process; if exceeded then set to *Failed*;\n* jobRerunAttemptNumber – `1` – number of attempts to re-run failed jobs;\n* jobRunInParallel – `false` – jobs will be executed in parallel processes (see [here](jobs.md#running-jobs-in-parallel-processes));\n* jobPoolConcurrencyNumber – `8` – max number of processes run simultaneously;\n* cronMinInterval – `2` – min interval (in seconds) between two cron runs;\n* daemonMaxProcessNumber – `5` – max number of processes run simultaneously;\n* daemonInterval – `10` – interval between process runs (in seconds);\n* daemonProcessTimeout – `36000` – max lifetime of a process run (in seconds);\n* jobE0MaxPortion – `100` – max portion of jobs executed in a single process for *e0* queue; this queue is intended for email sending; is run as often as possible;\n* jobQ0MaxPortion – `200` – *q0* is a queue for a general usage; is run as often as possible;\n* jobQ1MaxPortion – `500` – *q1* is a queue for a general usage; is run every minute;\n* jobGroupMaxPortion – `100` – a portion size for grouped jobs; \n\n### Mass Email\n\n* massEmailMaxAttemptCount – `3` – how many attempts to send an email will be made (can be helpful when SMTP server is gone away);\n* massEmailSiteUrl – to override the default site URL (can be helpful if there's no access to your CRM from the internet, but you need to handle opting out & tracking URLs; you will need to configure your server to handle requests to the specified URL);\n\n### Kanban\n\n* kanbanMaxOrderNumber – `50` – a number of records that can be ordered within a group; as of v6.1;\n* kanbanMinColumnWidth – `220` – a min width of column; the horizontal scrolling will appear to prevent column being shrunk less than the specified value; as of v7.1;\n\n### Text search\n\n* textFilterContainsMinLength  – `4` – actual if *Use 'contains' operator when filtering varchar fields* parameter is enabled;\n\n\n### PDF\n\n* pdfEngine – `Tcpdf` – what PDF engine to use; as of v6.1;\n* pdfFontFace – default font face;\n* pdfFontSize – default font size;\n\n### Events\n\n* eventAssignedUserIsAttendeeDisabled – `false` – If set *true*, then assigned user won't be automatically added to an attendee list (for meetings and calls);\n* eventInvitationForceSystemSmtp – `false` – To send invitation emails from system SMTP (otherwise a user's personal account can be used); as of v7.3;\n* busyRangesMaxRange – A max timeline range on which free/busy slots are displayed on the Scheduler panel.\n\n### Attachments\n\n* attachmentUploadMaxSize – `256` – max size of attachments in Mb; as of v7.2;\n* attachmentUploadChunkSize – `4` – chunk size in Mb; attachments uploaded by chunk; `0` disables uploading by chunk; as of v7.2;\n* inlineAttachmentUploadMaxSize – `20` – max size of inline attachments in Mb (e.g. inline images for emails);\n\n### Misc\n\n* starsLimit – 500 – max number of stars a user can give per entity type;\n* phoneNumberMaxCount – 10 – max number of phone numbers per record;\n* emailAddressMaxCount – 10 – max number of email addresses per record;\n* iframeSandboxExcludeDomainList – array of domains that do not require adding `sandbox=\"allow-scripts\"` in the Iframe dashlet; as of v9.0.7;\n* leadCaptureSiteUrl – to override the default site URL (can be helpful if there's no access to your CRM from the internet, but you want to expose the lead capture; you will need to configure your server to handle requests to the specified URL); as of v9.2;\n* wysiwygCodeEditorDisabled – `false` – disable the Wysiwyg field code editor; as of v8.2;\n* customPrefixDisabled – `false` – disable adding a *c* prefix to custom entity types, fields and links; as of v8.2; setting to true may cause conflicts; highly discouraged, voids official support;\n\n## Config files\n\n* `data/config.php` – the main config; can be written by the application or manually;\n* `data/config-internal.php` – for storing sensitive parameters that should never make their way to the front-end; can be written by the application or manually;\n* `data/config-override.php` – overrides parameters of the main config, supposed to be written only manually; you can read environment variables in there; as of v8.2;\n* `data/config-override-internal.php` – overrides parameters of the main config, supposed to be written only manually; for storing sensitive parameters; as of v8.2.\n\n"
  },
  {
    "path": "docs/administration/cron-on-windows.md",
    "content": "# Setting up Cron on Windows\n\n!!! note\n\n    All configuration settings listed here are made on **Windows Server 2019**.\n\nTo setup crontab on Windows system, take the following steps:\n\n1\\. Login as administrator into your EspoCRM instance.\n\n2\\. Go to the Scheduled Jobs section in the administrator panel (Menu > Administration > Scheduled Jobs) and copy the string for the crontab, replace  `php.exe` instead of `php-cgi.exe` and add `\"` symbols to the start and the end of the `php.exe` path. It looks like this one:\n\n```\n\"C:\\Program Files\\PHP\\v8.2\\php.exe\" -f C:\\inetpub\\wwwroot\\733\\cron.php\n```\n\n3\\. Create a batch file by using Notepad and save with the *.bat* extension with string from step 2.\n\n4\\. From the Windows Start menu, select Administrative Tools and then Task Scheduler.\n\n5\\. Create a folder inside Windows directory and Task inside.\n\n6\\. Configure the Task with the following settings and click `OK`:\n\n![IIS Manager](../_static/images/administration/iis/general.png)\n\n![IIS Manager](../_static/images/administration/iis/triggers.png)\n\n![IIS Manager](../_static/images/administration/iis/actions.png)\n\n![IIS Manager](../_static/images/administration/iis/conditions.png)\n\n![IIS Manager](../_static/images/administration/iis/settings.png)\n\n7\\. Right-click on the created Task and Click on `Run`.\n\n"
  },
  {
    "path": "docs/administration/currency.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Currency\n\nIn this article:\n\n* [Settings & rates](#settings-rates)\n* [Currency conversion](#currency-conversion)\n* [Currency rates API](#currency-rates-api)\n* [Adding missing currency](#adding-missing-currency)\n* [Conversion via formula](#conversion-via-formula)\n* [Decimal data type](#decimal-data-type)\n\n## Settings & rates\n\nAn administrator can configure currency-related parameters and rates at Administration > Currency. It's possible to specify which currencies will be available in the system in the *Currency List* parameter.\n\nParameters:\n\n* Currency List – The currencies available in the system.\n* Default Currency – The currency that is pre-set when creating a new record. Currency values are converted to the default currency when filtering records by a currency field, sorting by a currency field, generating a Grid report with currency fields.\n* Base Currency – The currency used as a base when specifying currency rates. It is usually the local currency in which the company operates.\n\n### Exchange rates\n\n*As of v9.3.*\n\nCurrency exchange rates are available under: Administration > Currency > Currency Rates button in the top-right corner. They can be also reached from the Global Search with the search *Currencies* query. The Currencies tab can be added to the navigation bar.\n\nCurrency exchange rates can be viewed or edited by:\n\n- Admin users\n- Users with access to the Currency scope\n\nA rate entry has a mandatory *Date* field. The rate with the latest non-future date is used as the current rate.\n\n### Default currency for specific field\n\nIt's possible to set an exclusive default currency for a specific field.\n\nFor example, for the *Amount* field of the *Opportunity*, set the *Default* value at Administration > Entity Manager > Opportunity > fields > amountCurrency.\n\n## Currency conversion\n\n### Converted field\n\nAll fields of *Currency* type are paired with a special read-only field of *Currency Converted* type. When you create a new Currency field, a Converted field is created automatically. This field represents a value converted to *Default Currency* based on current currency rates. This field is used for sorting by currency field, filtering, comparison, reporting. The field is read-only.\n\n!!! note\n\n    When currency rates are changed, the value of Currency Converted field is also changed. Technically the value is not stored, but calculated on-fly. This can cause an issue that your reports get changed every time currency rates are changed.   \n\nTo preserve converted values based on current rates you can:\n\n1. Convert currency manually. With mass action from the list view or action on the detail view.\n2. Convert currency automatically with the Workflows tool. Convert Currency service action is available for Opportunities, Quotes, Sales Orders, Invoices. E.g. you can setup a workflow that will update currencies for all closed opportunities each week.\n3. Utilize Formula to store a current converted value in a separate read-only field. You can use either a regular Before Save Script or the Workflow tool.\n\n### Storing current converted value\n\nLet's assume that you have a currency field named *amount*, and the default currency is *USD*.\n\nCreate a new field of *Currency* type, name it *amountLocal*, make it read-only. Note that for non-custom entities the field will be named *cAmountLocal*.\n\nAdd a Formula script to the *Before Save Script* in the Entity Manager. You can also use this formula in a Workflow rule.\n\n```\namountLocal = amountConverted;\namountLocalCurrency = 'USD';\n```\n\nYou can re-calculate formula for all existing records with a mass action from the list view.\n\nNote that some entity types may have already such a field implemented.\n\n### Convert currency manually\n\nIt's possible to manually convert all currency fields of a record.\n\n1. Mass action on the list view. Select which records you want to update (you can select all results). In *Actions* dropdown, click *Convert Currency*.\n2. Action on the detail view. Available in the dropdown next to *Edit* button.\n\n### Convert currency with Workflow\n\n*Convert Currency* service action is available for Opportunity, Quote, Sales Order, Invoice. E.g. you can set up a workflow that will update currencies for all closed opportunities each week.\n\n## Currency rates API\n\nThe API User needs to have *Currency* scope enabled in Roles.\n\nRequest to get all rates: `GET api/v1/CurrencyRate`.\n\nRequest to update specific rates: `PUT api/v1/CurrencyRate`, with JSON payload.\n\nPayload example:\n\n```\n{\n    \"EUR\": 1.11,\n    \"UAH\": 0.037\n}\n```\n\nRate values are related to *Base Currency* specified in Settings.\n\n## Adding missing currency\n\nIf a currency that you need is missing, you can add it manually.\n\nCreate a file: `custom/Espo/Custom/Resources/metadata/app/currency.json`\n\n```json\n{\n    \"list\": [\n        \"__APPEND__\",\n        \"COD\"\n    ]\n}\n\n```\n\nwhere *COD* is a 3-letter currency code in [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) standard.\n\nClear cache at Administration.\n\n## Conversion via formula\n\nExample (conversion from the default currency to EUR, for a field named *amount*):\n\n```\namountEur = amountConverted * record\\attribute('Currency', 'EUR', 'rate');\n```\n\nThe field *amountConverted* contains an automatically calculated value in the default currency. Such fields are automatically created for all currency fields.\n\nYou can also use the [ext\\currency\\convert](formula/ext.md#extcurrencyconvert) function to convert currency amounts.\n\n## Decimal data type\n\n*As of v7.4.*\n\nWhen precision is necessary for a specific currency field, it's recommended to use a Decimal data type. When creating a new currency field, check a corresponding checkbox.\n\nFor existing fields, can be enabled manually in metadata > entityDefs:\n\n```json\n{\n    \"fields\": {\n        \"myCurrencyField\": {\n            \"decimal\": true,\n            \"precision\": 13,\n            \"scale\": 4 \n        }\n    }\n}\n```\n\nRebuild is required after modifying an existing field. Can take long if the table is big. Run from CLI in this case.\n\nIf the parameters *precision* and *scale* are not defined, values 13, 4 are used.\n\nIn the application, amount values will be represented as strings (rather than floats). \n\nIn templates (PDF, email), you need to use the *numberFormat* helper to print currency values.\n"
  },
  {
    "path": "docs/administration/dashboards.md",
    "content": "# Dashboards\n\nAll internal users can manage their dashboards, including adding, removing, and configuring dashlets, as well as adding dashboard tabs. Users can lock their dashboard to prevent accidental changes.\n\nAn administrator can edit dashboards of other users. On the user detail view, click the *Preferences* item from the dropdown at the top-right corner. There, you can find *Dashboard Layout*.\n\nUsers can reset their dashboard layout to the default. On the Preferences edit view, click *Reset Dashboard to Default* from the dropdown next to the *Edit* button. The administrator can reset dashboards of other users.\n\nOn the dashboard:\n\n* Dashlets can be dragged by the header.\n* Dashlets can be resized by dragging the lower-right corner.\n* Multiple dashboard tabs can be created to group dashlets by their purpose.\n\n## System default dashboard\n\nThe default dashboard layout will be applied to all new users. This layout be changed at Administration > User Interface > Dashboard Layout.\n\n## Dashboard templates\n\nDashboard templates are available for administrators at Administration > Dashboard Templates. They provide the ability to deploy specific dashboard layouts to multiple users. It's also possible to deploy for all users of a specific team.\n\n## Portal dashboard\n\nOn the edit view of the Portal record, you can define its default dashboard layout. It will be applied to all portal users unless a user has a specific *Dashboard Template*.\n\nWhen editing a *Portal User*, you can specify the Dashboard Template for that user. This template will override the default template of the Portal.\n\n## Dashlet\n\nThis section covers several out-of-the-box dashlets.\n\n### Recort List\n\nThis dashlet allows users to display records of any entity type.\n\nParameters:\n\n- Primary Filter – for example, a user can select *Open* filter to display only open Tasks.\n- Additional Filters (known as Bool filters) – for example, a user can add *Only My* filter to display only records assignmed to them, or *Shared* filter to display records where they added as a collaborator.\n- Order By and Order\n- Layout\n\n### My Activities\n\nDisplays user's upcoming activities, such as Meetings, Calls, Tasks, and entity types of the Event type.\n\nParameters:\n\n- Next X Days – number of days into the future for which activities are displayed.\n- Include Shared – to include tasks where the user is added as s collaborator.\n\n### Iframe\n\nProvides the ability to display external site in an Iframe.\n\nParameters:\n\n- URL\n\n### Memo\n\nProvides the ability to display a specific text. Markdown is supported. It can be used to display instructions for users.\n\n### Calendar\n\nDisplays the user's calendar.\n\nPrameters:\n\n- Mode – the calendar mode.\n- What to display – what activity types to display.\n- Teams – optionally, to display activities of specific teams.\n\n### Stream\n\nDisplays the user's stream.\n\nParameters:\n\n- Don't show own records\n\n### My Inbox\n\nDisplays inbound emails.\n\n### Sales Pipeline\n\nA sales pipeline chart based on Opportunities.\n\nParameters:\n\n- Date Filter\n- Group by last reached stage\n- Team (optional)\n\n### Sales by Month\n\nA sales by month chart based on Opportunities.\n\nParameters:\n\n- Date Filter\n\n### Opportunities by Lead Source\n\nA chart.\n\nParameters:\n\n- Date Filter\n\n### Opportunities by Stage\n\nA chart.\n\nParameters:\n\n- Date Filter\n\n## See also\n\n* [Creating custom dashlet](../development/how-to-create-a-dashlet.md)\n"
  },
  {
    "path": "docs/administration/date-formatting.md",
    "content": "# Date & Time Formatting\n\n* `YYYY` – 4 digit year: `2020`\n* `YY` – 2 digit year: `20`\n* `M MM` – month number: `1..12`\n* `MMM MMMM` – month: `Jan..December`\n* `D DD` – day of month: `1..31`\n* `Do` – day of month with ordinal: `1st..31st`\n* `ddd dddd` – day of week: `Tue Tuesday`\n* `H HH` – hours (24 hour time): `0..23`\n* `h hh` – hours (12 hour time): `0..12`\n* `a A` – post or ante meridiem: `am PM`\n* `m mm` – minutes: `0..59`\n* `s ss` – seconds: `0..59`\n* `Z ZZ zz` – offset from UTC : `+02:00 +0200`\n* `zz` – timezone: `Europe/London`\n"
  },
  {
    "path": "docs/administration/docker/caddy.md",
    "content": "# Caddy and EspoCRM\n\nThe Caddy web server is an open-source, HTTP/2-enabled web server written in Go.\n\nTo connect Caddy and EspoCRM, you can use the Docker Compose environment. Also, you must have your own domain.\n\n1\\. Create a folder that will contain your EspoCRM files and database.\n\n2\\. Create here a `docker-compose.yml` file:\n\n#### docker-compose.yml\n\n```\nservices:\n\n  caddy:\n    image: caddy:latest\n    container_name: caddy\n    restart: always\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    volumes:\n      - ./certs:/etc/caddy/certs            # optional: if you have self-signed certificates\n      - ./Caddyfile:/etc/caddy/Caddyfile\n    environment:\n      - ACME_AGREE=true                     # to automatically obtain certificates\n\n  espocrm-db:\n    image: mariadb:latest\n    container_name: espocrm-db\n    environment:\n      MARIADB_ROOT_PASSWORD: root_password\n      MARIADB_DATABASE: espocrm\n      MARIADB_USER: espocrm\n      MARIADB_PASSWORD: database_password\n    volumes:\n      - espocrm-db:/var/lib/mysql\n    restart: always\n    healthcheck:\n      test: [\"CMD\", \"healthcheck.sh\", \"--connect\", \"--innodb_initialized\"]\n      interval: 20s\n      start_period: 10s\n      timeout: 10s\n      retries: 3\n\n  espocrm:\n    image: espocrm/espocrm\n    container_name: espocrm\n    environment:\n      ESPOCRM_DATABASE_PLATFORM: Mysql\n      ESPOCRM_DATABASE_HOST: espocrm-db\n      ESPOCRM_DATABASE_USER: espocrm\n      ESPOCRM_DATABASE_PASSWORD: database_password\n      ESPOCRM_ADMIN_USERNAME: admin\n      ESPOCRM_ADMIN_PASSWORD: password\n      ESPOCRM_SITE_URL: \"https://{YOUR_DOMAIN}\"\n    volumes:\n      - espocrm:/var/www/html\n    restart: always\n    depends_on:\n      espocrm-db:\n        condition: service_healthy\n    expose:\n      - 80\n\n  espocrm-daemon:\n    image: espocrm/espocrm\n    container_name: espocrm-daemon\n    volumes:\n      - espocrm:/var/www/html\n    restart: always\n    depends_on:\n      - espocrm\n    entrypoint: docker-daemon.sh\n\n  espocrm-websocket:\n    image: espocrm/espocrm\n    container_name: espocrm-websocket\n    environment:\n      ESPOCRM_CONFIG_USE_WEB_SOCKET: \"true\"\n      ESPOCRM_CONFIG_WEB_SOCKET_URL: \"wss://{YOUR_DOMAIN}/ws\"\n      ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN: \"tcp://*:7777\"\n      ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN: \"tcp://espocrm-websocket:7777\"\n    volumes:\n      - espocrm:/var/www/html\n    restart: always\n    depends_on:\n      - espocrm\n    entrypoint: docker-websocket.sh\n    expose:\n      - 8080\n\nvolumes:\n  espocrm:\n  espocrm-db:\n```\n\n3\\. Create here a `Caddyfile` text file:\n\n#### Caddyfile\n\n```\nespocrm-example.com {\n    reverse_proxy espocrm:80\n\n    reverse_proxy /ws espocrm-websocket:8080 {\n        header_up Host {host}\n        header_up X-Real-IP {remote}\n        header_up X-Forwarded-For {remote}\n        header_up X-Forwarded-Proto {scheme}\n    }\n\n    # Optional for Self-Signed SSL Certificate\n    # tls /etc/caddy/certs/myserver.crt /etc/caddy/certs/myserver.key\n}\n```\n\n----\n\nNow, start containers with the CLI command `docker compose up -d`.\n"
  },
  {
    "path": "docs/administration/docker/installation.md",
    "content": "# EspoCRM with Docker\n\nIn this article:\n\n- [Installing with Docker](#install-espocrm-with-docker)\n- [Installing with Docker Compose](#install-espocrm-with-docker-compose)\n- [Installing with Traefik](#install-espocrm-with-traefik)\n- [Installing with Caddy](#install-espocrm-with-caddy)\n- [Upgrading](#upgrading)\n- [Shutdown and cleanup](#shutdown-and-cleanup-containers)\n- [Running a shell](#running-a-shell)\n- [Environments](#installation-environments)\n- [Config Environments](#config-environments)\n- [Image Variants](#image-variants)\n- [Troubleshooting](#troubleshooting)\n\n\n## Install EspoCRM with Docker\n\nOne of the ways to install EspoCRM is by using its official Docker Image. The EspoCRM Container Package contains the Docker image, which incorporates all the required files and dependencies to launch EspoCRM in development or production environments. You can use Docker to run EspoCRM in an isolated environment built with Docker containers.\n\nEspoCRM image requires to run MariaDB or MySQL server:\n\n```\n$ docker run --name mariadb -e MARIADB_ROOT_PASSWORD=password -d mariadb:latest\n```\n\n- `mariadb` — name of MariaDB container,\n- `MARIADB_ROOT_PASSWORD=password` — you can change `password` to any password you want,\n- `mariadb:latest` — [MariaDB image](https://hub.docker.com/_/mariadb/tags) version.\n\nRun EspoCRM container:\n\n```\n$ docker run --name my-espocrm --link mariadb:mariadb -d espocrm/espocrm\n```\n\n- `my-espocrm` — name of EspoCRM container,\n- `mariadb:mariadb` — name (link) of MariaDB container,\n- `espocrm/espocrm` — [EspoCRM image](https://hub.docker.com/r/espocrm/espocrm/tags) version.\n\n#### Run EspoCRM container via a specific port:\n\n```\n$ docker run --name my-espocrm -p 8080:80 --link mariadb:mariadb -d espocrm/espocrm\n```\n\nThen, access it via `http://localhost:8080` with credentials admin and password.\n\n#### Run EspoCRM via a specific IP or a domain with a port:\n\n```\n$ docker run --name my-espocrm -e ESPOCRM_SITE_URL=http://172.20.0.100:8080 -p 8080:80 --link mariadb:mariadb -d espocrm/espocrm\n```\n\nThen, access it via `http://172.20.0.100:8080` with credentials **admin** and **password**.\n\n## Install EspoCRM with Docker Compose\n\nYou can use Docker Compose to run EspoCRM in an isolated environment built with Docker containers. Before starting, make sure you have [Compose](https://docs.docker.com/compose/install/) installed.\n\n1\\. Create an empty directory.\n\n```\n$ mkdir espocrm-docker\n```\n\n2\\. Change into this directory.\n\n```\n$ cd espocrm-docker/\n```\n\n3\\. Create a **`docker-compose.yml`** file:\n\n```\nservices:\n\n  espocrm-db:\n    image: mariadb:latest\n    container_name: espocrm-db\n    environment:\n      MARIADB_ROOT_PASSWORD: root_password\n      MARIADB_DATABASE: espocrm\n      MARIADB_USER: espocrm\n      MARIADB_PASSWORD: database_password\n    volumes:\n      - espocrm-db:/var/lib/mysql\n    restart: always\n    healthcheck:\n      test: [\"CMD\", \"healthcheck.sh\", \"--connect\", \"--innodb_initialized\"]\n      interval: 20s\n      start_period: 10s\n      timeout: 10s\n      retries: 3\n\n  espocrm:\n    image: espocrm/espocrm\n    container_name: espocrm\n    environment:\n      ESPOCRM_DATABASE_PLATFORM: Mysql\n      ESPOCRM_DATABASE_HOST: espocrm-db\n      ESPOCRM_DATABASE_USER: espocrm\n      ESPOCRM_DATABASE_PASSWORD: database_password\n      ESPOCRM_ADMIN_USERNAME: admin\n      ESPOCRM_ADMIN_PASSWORD: password\n      ESPOCRM_SITE_URL: \"http://localhost:8080\"\n    volumes:\n      - espocrm:/var/www/html\n    restart: always\n    depends_on:\n      espocrm-db:\n        condition: service_healthy\n    ports:\n      - 8080:80\n\n  espocrm-daemon:\n    image: espocrm/espocrm\n    container_name: espocrm-daemon\n    volumes:\n      - espocrm:/var/www/html\n    restart: always\n    entrypoint: docker-daemon.sh\n\n  espocrm-websocket:\n    image: espocrm/espocrm\n    container_name: espocrm-websocket\n    environment:\n      ESPOCRM_CONFIG_USE_WEB_SOCKET: \"true\"\n      ESPOCRM_CONFIG_WEB_SOCKET_URL: \"ws://localhost:8081\"\n      ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN: \"tcp://*:7777\"\n      ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN: \"tcp://espocrm-websocket:7777\"\n    volumes:\n      - espocrm:/var/www/html\n    restart: always\n    entrypoint: docker-websocket.sh\n    ports:\n      - 8081:8080\n\nvolumes:\n  espocrm-db:\n  espocrm:\n```\n\nMore about *Installation Environments* you can find [here](#installation-environments).\n\n4\\. Build EspoCRM project from directory.\n\n```\n$ docker compose up -d\n```\n\n5\\. Bring up EspoCRM in a web browser. You can use http://localhost as the IP address, and open http://localhost:8080 in a web browser.\n\n### Install EspoCRM with Traefik\n\nYou can read the instructions for installing EspoCRM in conjunction with Traefik in the Docker Compose environment [here](https://docs.espocrm.com/administration/docker/traefik/).\n\n### Install EspoCRM with Caddy\n\nYou can read the instructions for installing EspoCRM in conjunction with Caddy in the Docker Compose environment [here](https://docs.espocrm.com/administration/docker/caddy/).\n\n### Upgrading\n\nIn order to upgrade the container created by the `docker-compose.yml`:\n\n1. Open your EspoCRM container directory.\n2. Run the command:\n\n  ```\n  $ docker compose pull && docker compose up -d\n  ```\n\nWithin a few minutes the container will be upgraded to the latest version.\n\n### Shutdown and cleanup containers\n\nThe `docker compose down` command removes the containers and default network, but preserves EspoCRM database.\n\nThe `docker compose down --volumes` removes the containers, default network, and the EspoCRM database.\n\n### Running a shell\n\nIn order to enter the container and view the files, make a rebuild, etc., use the following command (`espocrm` is your container name):\n\n```\n$ docker exec -it espocrm bash\n```\n\n## Installation Environments\n\nThis is one-time environment variables which are using only for the fresh installation. If you need to define configuration options on the container startup, see the [Config Environments](#config-environments).\n\n#### ESPOCRM_DATABASE_PLATFORM\n\nDatabase platform. The possible values: `Mysql` or `Postgresql`. The default value is `Mysql`.\n\n#### ESPOCRM_DATABASE_HOST\n\nDatabase host name for EspoCRM. The default value is `espocrm-db`.\n\n#### ESPOCRM_DATABASE_PORT\n\nDatabase port for EspoCRM. The default value is empty.\n\n#### ESPOCRM_DATABASE_NAME\n\nDatabase name for EspoCRM. The default value is `espocrm`.\n\n#### ESPOCRM_DATABASE_USER\n\nDatabase user for EspoCRM. The default value is `root`.\n\n#### ESPOCRM_DATABASE_PASSWORD\n\nDatabase password for EspoCRM. The default value is `password`.\n\n#### ESPOCRM_ADMIN_USERNAME\n\nUser name for an administrator of EspoCRM. The default value is `admin`.\n\n#### ESPOCRM_ADMIN_PASSWORD\n\nUser password for an administrator of EspoCRM. The default value is `password`.\n\n#### ESPOCRM_SITE_URL\n\nThe URL of EspoCRM. This option is very important for normal operating of EspoCRM. Examples: `http://172.20.0.100:8080`, `http://my-crm.local`.\n\n### Other optional options\n\nThe list of possible values and their default values can be found in EspoCRM Administrator panel > Settings.\n\n-\t`ESPOCRM_LANGUAGE`\n-\t`ESPOCRM_DATE_FORMAT`\n-\t`ESPOCRM_TIME_FORMAT`\n-\t`ESPOCRM_TIME_ZONE`\n-\t`ESPOCRM_WEEK_START`\n-\t`ESPOCRM_DEFAULT_CURRENCY`\n-\t`ESPOCRM_THOUSAND_SEPARATOR`\n-\t`ESPOCRM_DECIMAL_MARK`\n\n## Config Environments\n\nThese environment variables are using to define configuration parameters of the EspoCRM every time on the container startup. The parameters that can be changed are defined in the `data/config.php` or `data/config-internal.php`.\n\n### Naming\n\nConfig environment variables should be converted from the camel-case format. For example:\nThe `exportDisabled` config option should be converted to `ESPOCRM_CONFIG_EXPORT_DISABLED`.\n\n### Logger\n\nThere are additional options to change the `logger`:\n\n- `ESPOCRM_CONFIG_LOGGER_LEVEL: \"DEBUG\"`\n- `ESPOCRM_CONFIG_LOGGER_MAX_FILE_NUMBER: 30`\n- `ESPOCRM_CONFIG_LOGGER_PATH: \"data/logs/espo.log\"`\n\nFor more details, visit [documentation](../log.md).\n\n### Allowed types:\n\n#### String\n```\nESPOCRM_CONFIG_WEB_SOCKET_URL: \"wss://my-espocrm.com:8080\"\n```\n\n#### Integer\n```\nESPOCRM_CONFIG_EMAIL_MESSAGE_MAX_SIZE: 10\n```\n\n#### Boolean\n```\nESPOCRM_CONFIG_USE_WEB_SOCKET: \"true\"\n```\n\n#### Null\n```\nESPOCRM_CONFIG_CURRENCY_DECIMAL_PLACES: \"null\"\n```\n\n## Image Variants\n\nThe `espocrm` images come in many flavors, each designed for a specific use case.\n\n- `espocrm:apache`\n- `espocrm:fpm`\n- `espocrm:fpm-alpine`\n- `espocrm:<version>`\n- `espocrm:<version>-apache`\n- `espocrm:<version>-fpm`\n- `espocrm:<version>-fpm-alpine`\n\n## Troubleshooting\n\n### Switching to MySQL 8.4\n\nIn MySQL 8.4 there were changes in the authentication procedure, so you may encounter authentication related errors while upgrading EspoCRM. In this case, it is recommended to take the following steps:\n\n1\\. Change *authentication plugin* to `caching_sha2_password` for your MySQL users:\n\nNotes:\n\n- Replace the `YOUR_ROOT_PASSWORD` with your MySQL root password.\n- Replace the `YOUR_ESPOCRM_DB_PASSWORD` with your MySQL espocrm user password.\n\n```\nsudo docker exec -i mysql mysql --user=root -p -e \"\n  ALTER USER IF EXISTS 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'YOUR_ROOT_PASSWORD';\n  ALTER USER IF EXISTS 'root'@'%' IDENTIFIED WITH caching_sha2_password BY 'YOUR_ROOT_PASSWORD';\n  ALTER USER IF EXISTS 'espocrm'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'YOUR_ESPOCRM_DB_PASSWORD';\n  ALTER USER IF EXISTS 'espocrm'@'%' IDENTIFIED WITH caching_sha2_password BY 'YOUR_ESPOCRM_DB_PASSWORD';\"\n```\n\n2\\. Remove from *docker-compose.yml* file the following line: `command: --default-authentication-plugin=mysql_native_password`.\n\n3\\. Restart and build `mysql` container:\n\n```\nsudo docker stop mysql && sudo docker rm mysql\ndocker compose up -d --build\n```\n"
  },
  {
    "path": "docs/administration/docker/traefik.md",
    "content": "# Traefik and EspoCRM\n\nTraefik is an open-source reverse proxy that makes it easy to work with microservices and/or just containers with your applications.\n\nTo connect Traefik and EspoCRM, you can use the Docker Compose environment. Also, you must have your own domain.\n\n1. Create a folder that will contain your EspoCRM files and database.\n2. Create here a `docker-compose.yml` file:\n\n#### docker-compose.yml\n\n```\nservices:\n\n  traefik:\n    image: traefik:latest\n    container_name: traefik\n    command:\n      - --api.insecure=true\n      - --providers.docker=true\n      - --providers.docker.exposedbydefault=false\n      - --entrypoints.websecure.address=:443\n      - --entrypoints.web.address=:80\n      - --entrypoints.web.http.redirections.entryPoint.to=websecure\n      - --entrypoints.web.http.redirections.entryPoint.scheme=https\n      - --entrypoints.web.http.redirections.entrypoint.permanent=true\n      - --certificatesresolvers.esporesolver.acme.tlschallenge=true\n      - --certificatesresolvers.esporesolver.acme.email={EMAIL_ADDRESS}\n      - --certificatesresolvers.esporesolver.acme.storage=/letsencrypt/acme.json\n    ports:\n      - \"80:80\"             \n      - \"8080:8080\"    \n      - \"443:443\"       \n    volumes:\n      - ./letsencrypt:/letsencrypt                                      \n      - /var/run/docker.sock:/var/run/docker.sock:ro     \n\n  espocrm-db:\n    image: mariadb:latest\n    container_name: espocrm-db\n    command: --max-allowed-packet=64MB\n    restart: always\n    healthcheck:\n      test: [\"CMD\", \"healthcheck.sh\", \"--connect\", \"--innodb_initialized\"]\n      interval: 20s\n      start_period: 10s\n      timeout: 10s\n      retries: 3\n    environment:\n      MARIADB_ROOT_PASSWORD: root_password\n      MARIADB_DATABASE: espocrm\n      MARIADB_USER: espocrm\n      MARIADB_PASSWORD: database_password\n    volumes:\n      - ./espocrm-db:/var/lib/mysql\n\n  espocrm:\n    image: espocrm/espocrm:latest\n    container_name: espocrm\n    environment:\n      ESPOCRM_DATABASE_HOST: espocrm-db\n      ESPOCRM_DATABASE_USER: espocrm\n      ESPOCRM_DATABASE_PASSWORD: database_password\n      ESPOCRM_ADMIN_USERNAME: admin\n      ESPOCRM_ADMIN_PASSWORD: password\n      ESPOCRM_SITE_URL: \"https://{ESPOCRM_DOMAIN}\"\n    restart: always\n    depends_on:\n      espocrm-db:\n        condition: service_healthy\n    volumes:\n      - ./espocrm:/var/www/html\n    labels:\n      - traefik.enable=true                                           \n      - traefik.http.routers.espocrm-app.rule=Host(`{ESPOCRM_DOMAIN}`)\n      - traefik.http.routers.espocrm-app.entrypoints=websecure\n      - traefik.http.routers.espocrm-app.tls=true\n      - traefik.http.routers.espocrm-app.tls.certresolver=esporesolver\n\n  espocrm-daemon:\n    image: espocrm/espocrm:latest\n    container_name: espocrm-daemon\n    volumes:\n      - espocrm:/var/www/html\n    restart: always\n    entrypoint: docker-daemon.sh\n\n  espocrm-websocket:\n    image: espocrm/espocrm:latest\n    container_name: espocrm-websocket\n    environment:\n     ESPOCRM_CONFIG_USE_WEB_SOCKET: \"true\"\n     ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN: \"tcp://*:7777\"\n     ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN: \"tcp://espocrm-websocket:7777\"\n    volumes:\n      - espocrm:/var/www/html\n    restart: always\n    entrypoint: docker-websocket.sh\n    labels:\n      - traefik.enable=true\n      - traefik.http.routers.espocrm-ws.rule=Host(`{ESPOCRM_DOMAIN}`) && PathPrefix(`/ws`)\n      - traefik.http.routers.espocrm-ws.entrypoints=websecure\n      - traefik.http.routers.espocrm-ws.tls=true\n      - traefik.http.routers.espocrm-ws.tls.certresolver=esporesolver\n      - traefik.http.services.espocrm-ws.loadbalancer.server.port=8080\n\nvolumes:\n  espocrm-db:\n  espocrm:\n```\n\nTraefik container commands explanation:\n\n- **api.insecure=true** – *Enable the API in insecure mode. You can access Traefik Dashboard at `your_server_IP:8080`*\n- **providers.docker=true** – *Enable Docker as the provider for Traefik*\n- **providers.docker.exposedbydefault=false** – *Don't expose every container to Traefik, only expose enabled ones*\n- **entrypoints.websecure.address=:443** – *Define an entrypoint for HTTPS on port :443 named websecure*\n- **entrypoints.web.address=:80** – *Define an entrypoint for port :80 named web*\n- **entrypoints.web.http.redirections.entryPoint.to=websecure** – *Redirect all incoming requests to entrypoint websecure*\n- **entrypoints.web.http.redirections.entryPoint.scheme=https** – *Redirection target scheme*\n- **entrypoints.web.http.redirections.entrypoint.permanent=true** – *Apply a permanent redirection*\n- **certificatesresolvers.esporesolver.acme.tlschallenge=true** – *Enable TLS-ALPN-01 to generate and renew ACME certificates*\n- **certificatesresolvers.esporesolver.acme.email=`{EMAIL_ADDRESS}`** – *Setting email for certificates*\n- **certificatesresolvers.esporesolver.acme.storage=/letsencrypt/acme.json** – *Defining acme.json file to store certificates information*\n\nEspoCRM container commands explanation:\n\n- **traefik.enable=true** – *Enable Traefik to proxy main EspoCRM container*                              \n- **traefik.http.routers.espocrm-app.rule=Host(`{ESPOCRM_DOMAIN}`)** – *Your domain name goes here for the HTTP rule* \n- **traefik.http.routers.espocrm-app.entrypoints=websecure** – *Define entrypoint for HTTPS* \n- **traefik.http.routers.espocrm-app.tls=true** – *Make sure all routers tied to this entrypoint are using HTTPS by default* \n- **traefik.http.routers.espocrm-app.tls.certresolver=esporesolver** – *Define certificates resolvers for HTTPS* \n\n> The labels in the EspoCRM container for WebSocket works in exactly the same way, we only add a prefix to the host and open port 8080 for container.\n\n----\n\nNow, start containers with the CLI command `docker compose up -d`.\n\nYou can track the work of Traefik on the Dashboard at *your_server_IP:8080*.\n\nEspoCRM will work with both HTTP and HTTPS on your domain.\n"
  },
  {
    "path": "docs/administration/dynamic-logic.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Dynamic Logic\n\nA dynamic behavior for forms can be achieved by utilizing the Dynamic Logic feature.\n\n## Fields\n\nDynamic Logic parameters are available for every field (Administration > Entity Manager > {Entity Type} > Fields > {field}.\n\nThe Dynamic Logic allows you to define conditions making certain fields visible, required or read-only. Conditions will be\nchecked automatically when data in the form is changed.\n\nFor *Enum*, *Array*, *Multi-Enum*, *Checklist* fields it's, possible to define different sets of options that will be\navailable for the field depending on which condition is met. Note that the order of option list is taken into account.\n\nDynamic logic can control:\n\n* Visibility − if the field is visible or not;\n* Required − if the field is required or not;\n* Read-only − if the field read-only or not;\n* Options − conditions that determine options available for enum fields;\n* Invalidity − conditions making the field invalid.\n\nConditions are configured through user interface, no coding required.\n\n![Condition builder](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/dynamic-logic/1.png)\n\n!!! note\n\n    * When a condition for a field checks the value of the same field, it may cause side effects. E.g. making a field read-only when the same field is not empty.\n    * When defining enum options that depend on the current value of the field, you need to include the current value to the option set.\n    * In some cases it may be reasonable to disable the inline-edit functionality for a specific field as it may interfere with the dynamic logic.\n    * Dynamic Logic operates fields on the form, it has no effect on buttons and menu items in the UI.\n    * Dynamic Logic is not applied on the list view.\n\n### Field logic\n\n#### Visible\n\nIs applied only in the frontend.\n\n#### Required\n\nIs applied only in the frontend and in the backend (as of v9.1).\n\n#### Read-only\n\nIs applied only in the frontend. Conditions are checked against the current state of the record. If we change a record without saving it, it changes the current state.\n\n#### Read-only saved-state\n\n*As of v9.1.*\n\nDynamic logic conditions checked against the saved state of the record. The logic is not applied while editing a record without saving.\n\n* Is not applied when a record is created.\n* Applied in both the frontend and the backend.\n* Applied in mass-update.\n\nUse-case: Make a field Resolution read-only when Status = Completed. It won't be possible to write the Resolution field while the Status is saved as Completed. Even if we change the Status on the form, the Resolution field will still be read-only. But if we change and save the Status, it will be possible to write the Resolution field.\n\n#### Options\n\nA mapping of conditions against option lists. Specific conditions determine what options will be available in an enum field.\n\nFor Enum, Array, Multi-Enum and Checklist fields.\n\n### Regular expression\n\nFor *Varchar* and *Text* fields, it's possible to define a regular expression to check whether a value matches a specific\npattern.\n\nAn expression should start and end with a slash character.\n\nExample: `/^\\d{5}-\\d{6}-\\d{2}$/`\n\nYou can also specify regular expression flags after the ending slash.\n\n## Panels\n\nIn the Layout Manager, you can specify conditions making a specific panel visible. Edit the panel to configure the dynamic logic.\n\nAvailable in the following layouts:\n\n* Detail\n* Side Panels\n* Bottom Panels\n\nIt's also possible to define conditions on which a specific color will be applied to the panel.\n\n## Misc\n\nTo determine whether a record is being created, check whether the ID is empty. It can be useful to hide some fields when the record not yet created or to show some panel with instructions described in a panel note.\n\nFor dynamic logic that is applied only in the frontend, you may consider additionally using an API Before-Save script for a validation purpose.\n\n## See also\n\n* [Dynamic Logic quick tour](https://app.supademo.com/demo/cmke83sqa1io5qm44yrnnenp8)\n"
  },
  {
    "path": "docs/administration/email-fetching.md",
    "content": "# Emails\n\nThe document is moved to [here](emails.md).\n"
  },
  {
    "path": "docs/administration/emails.md",
    "content": "---\nsearch:\n  boost: 3\n---\n\n# Email Administration\n\n!!! important\n\n    [Cron](server-configuration.md#setting-up-crontab) should be configured in your system to make email fetching work.\n\n## Overview\n\nEspoCRM has the ability to monitor IMAP mailboxes. Emails can be fetched by Group Email Accounts and Personal Email Accounts. Group Email Accounts represent group mailboxes: the most common case is a support-team mailbox. Personal Email Accounts represent personal mailboxes of users.\n\nAs an email is coming, the system tries to link it with an appropriate record (Accounts, Lead, Opportunity, Case). Users who follow that record will receive a notification about the new email in the system, even if they are not recipients of the email.\n\n!!! warning \"Important\"\n\n    Email records **are not duplicated** in the system, even if they are fetched by different email accounts. If you remove an email record from the CRM, it will be removed for all users. It's recommended to **move to trash** instead. It's also recommended to restrict *delete* access for users in Roles.\n\nAn Email record can be assigned to a particular user. By default, the Assigned User field is not available on the layout. The administrator can add it at: Administration > Entity Manager > Side Panel Fields.\n\n## Access control\n\nAccess to imported emails is controlled by Roles. It means that if a particular email was imported from a mailbox of some user, other users will be able to see that email if they have access to that email.\n\nIf a user has a *read* access level set to *own*, they will be able to see emails that are related to them through at least one of the following links: Users, Assigned Users, Assigned User, Created By. Note than an email is automatically gets related with a user through the Users links if the user's email address is either in the *From*, *To* or *CC*.\n\nThere are 4 access levels: No, Own, Team, All.\n\n## Group email accounts\n\nGroup Email Accounts can be accessed at Administration > Group Email Accounts.\n\nOnly administrator can setup Group Email Accounts. Group Email Accounts can be used for both receiving and sending emails.\n\nThe *Teams* field determines which teams incoming emails will be assigned to. \n\nIf a Group Email Account has the SMTP enabled and it's checked as **shared**, then users will be able to use this account when sending emails. Access to the account for sending is controlled by Roles through the *Group Email Account* permission. If the permission level is set to *teams*, then users of the teams selected in the *Teams* field of the Group Email Account will be able to use that Group Email Account.\n\nThere is the ability to make the system send an **auto-reply** for emails incoming to a Group Email Account.\n\n### System email account\n\nOne Group Email Account needs to be picked as the system default account. All notifications and system emails will be sent from that account.\n\n1. Create and configure a Group Email Account (at Administration > Group Email Accounts).\n2. Navigate to Administration > Outbound Emails.\n3. Specify the email address in the *System Email Address* field. The email address must be exactly the same as in the created Group Email Account (the list of available accounts will be shown in an autocomplete dropdown).\n\n### Email-to-Case\n\nThere is an option to make the system create a new Case record from each email incoming to a specific Group Email Account. Cases can be distributed to users of a specific Team. There are three available distribution rules: *Direct Assignment*, *Round-Robin* and *Less-Busy*. \n\n!!! note\n\n    Only the first email in the thread creates a new Case. Every subsequent email will be linked to the existing Case record and a Note will be added to the Stream.\n\nWhen a user wants to send a reply to a customer, they need to make sure that the Case is selected as a **parent** of the email that is being sent. It will add the group email address to the *Reply-To* field of the email. So the customer's reply will be sent to the group address rather than to the user’s one.\n\n## Personal email accounts\n\nRegular users can set up their own email accounts that need to be monitored (at Emails tab > top right dropdown menu > Personal Email Accounts).\n\nThe administrator also can manage Personal Email Accounts of users (at Administration > Personal Email Accounts).\n\n!!! warning \"Important\"\n\n    By default, regular users don’t have **access** to Personal Email Accounts. The Administrator needs to allow access to the *Personal Email Accounts* scope in Roles.\n\n!!! warning \"Important\"\n\n    This is required to have the email functionality working properly. User records need to have their email address (or multiple addresses) set in the *Email* field. Only the administrator can change the *Email* field for users. It's supposed that the user's email address is the same as the email address of the user's Personal Email Account.\n\n## Email filters\n\nEmail Filters provide the ability to automatically filter incoming emails based to specified criteria. For example, if you don't want notification messages sent by some application to be imported to EspoCRM, you can create a filter to make EspoCRM skip them.\n\nThe administrator can create **global** filters applied to all email accounts. Users can create filters for their own Personal Email Account and for their entire Inbox.\n\nAvailable filter parameters:\n\n- From\n- To\n- Subject\n- Body Contains\n- Body Contains All\n\nIf any of specified filter parameters does not match for a particular email, then the filter is not applied.\n\nWildcard (*) can be used in filter parameters.\n"
  },
  {
    "path": "docs/administration/entity-manager.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Entity Manager\n\nThe Entity Manager is an essential part of EspoCRM. It allows using the system as a platform for custom business application development, as well as customizing the default CRM features.\n\nWith the Entity Manager, you can:\n\n* Add new entity types.\n* Customize existing entity types: change labels, default order and many other parameters.\n* Configure fields: add new and customize existing ones.\n* Configure relationships: add new, change labels and parameters of existing ones.\n\nThe Entity Manager tool is available from the Administration panel.\n\nAll customizations made via the Entity Manager are stored in the `custom` directory. You can make customizations on a separate instance, then [copy](#copying-customizations-to-another-instance) them to another instance.\n\n!!! note\n\n    When creating a new entity type, a field or relationship in an existing entity type, the system will add a prefix *c* to the name (meaning custom). The purpose of it is to prevent naming conflicts with future versions. This behavior can be disabled with the config parameter `customPrefixDisabled`. Disable it at your own risk.\n\nIn this article:\n\n* [Creating new entity type](#creating-new-entity-type)\n* [Entity type parameters](#entity-type-parameters)\n* [Fields](#fields)\n* [Relationships](#relationships)\n* [Formula](#formula)\n* [Copying customizations to another instance](#copying-customizations-to-another-instance)\n\nSee also:\n\n* [Quick tour](https://app.supademo.com/demo/cmc39h2hnlaf0sn1ru3j5yul5)\n\n## Creating new entity type\n\nClick the *Create Entity* button on the Entity Manager main page (Administration > Entity Manager). Specify the name, labels and select the type. If you select the *Person* type, your entity will have Email, Phone, First Name, Last Name and Salutation fields. Check the *Stream* if you want to have the Stream panel (users will be able to follow records).\n\nTypes:\n\n* Base – has only basic fields created by default: Name, Assigned User, Teams, Description.\n* Base Plus – like the Base type but with the Activities, History, Tasks panels.\n* Event – has the Date Start, Date End, Duration, Parent, Status fields; available in the Calendar and in the Activities panel (must be [enabled](../user-guide/activities-and-calendar.md#custom-entities-on-calendar) at Administration > Settings).\n* Person – has the Email, Phone, First Name, Last Name, Salutation, Address fields; the Activities, History, Tasks panels.\n* Company – has the Email, Phone, Billing Address, Shipping Address fields; the Activities, History, Tasks panels.\n\n## Entity type parameters\n\nIf you click *Edit* on the entity view, you will be able to change parameters of that entity type.\n\n* Labels – singular and plural names of the entity type.\n* Default order – how records are sorted in list views by default.\n* Stream – enables the Stream feature for the entity type.\n* Stars – the ability to star records; stars can be used by users to bookmark specific records.\n* Disabled – check if you don't need this entity type in the system.\n* Text Filter Fields – defines which fields are searched by the main text filter and global search.\n* Status Field – specifies which field (of enum type) will be used to represent the record status; required for the Kanban view.\n* Kanban view – enables the Kanban view mode; the parameter is available only if the Status Field is specified. \n* Full-Text Search – enables full-text search; see more [here](../user-guide/text-search.md#full-text-search).\n* Disable record count – the total number won't be displayed on the list view; can decrease loading time when the DB table is big.\n* Color – a color for a quick recognition.\n* Icon – pick an icon for the entity type.\n* Preserve Audit Log – disables cleanup of the audit log; this parameter is applicable only if Stream is disabled, since if Stream is enabled, audit log records are not being deleted.\n* Collaborators – the ability to [share](roles-management.md#collaborators) records with specific users.\n* Multiple Assigned Users – the ability to assign multiple users to a record.\n* Categories – records can be organized into tree-like categories; available for Base and Base Plus types (as of v10.0).\n* Lockable – enables record locking (as of v10.0).\n* Transactional Save – enables wrapping saves and removals into DB transactions (as of v10.0).\n\n!!! note\n\n    Some parameters are not available for certain entity types.\n\n## Fields\n\nBy clicking the *Fields* button, you will be moved to a separate page. There, you will be able to create new fields or update existing ones.\n\nSee [more detail](fields.md) about fields in the separate article.\n\n!!! important\n\n    After you created a new field, you may also need to put this field on [layouts](layout-manager.md) (Administration > Layout Manager).\n\n    You also need to add the field to the Search Filters layout to be able to search by the field on the list view.\n\n## Relationships\n\nYou can create custom relationships between entity types. Both standard and custom entities can be related to each other.\n\nIt's possible to create a relationship between the same entity type. E.g. a Company can have a parent company and child companies.\n\nIt's possible to have multiple relationships between the same entity type pairs. E.g. a Person and an Event can be linked by two relationships: attendees and organizers.\n\nRelationship types are listed below.\n\n#### One-to-Many\n\nAfter you created the relationship, a *Link* field will be automatically created for the right-side entity type. You can add the link field to the Detail layout (at Administration > Entity Manager > {Entity Type} > Layouts > Detail). You can also add the relationship panel to the left entity type (at Administration > Entity Manager > {Entity Type} > Layouts > Bottom Panels).\n\n#### Many-to-One\n\nThe same as One-to-Many but vice versa.\n\n#### Many-to-Many\n\nAfter you created the relationship, relationship panels will be available on both sides (at Administration > Entity Manager > {Entity Type} > Layouts > Bottom Panels).\n\n#### One-to-One Right\n\nThe *Link* field will be created in the current entity type (left), the *Link-One* field – in the foreign entity type (right). It does not matter which one-to-one type to choose from the user perspective.\n\n#### One-to-One Left\n\nThe same as previous but vice versa. The *Link* field will be created in the foreign entity type.\n\n#### Children-to-Parent\n\nLinking with multiple entity types through the *Link-Parent* field.\n\n*Foreign Links* checkboxes allows you to create Has-Children links in specific parent entity types. For example, if we check *Account* foreign link, it will create a link in the Account entity type. It will allow to add relationship panel in Account.\n\n### Parameters\n\n#### Link Multiple field\n\nThe parameter *Link Multiple Field* implies that the field of the *Link-Multiple* type will be created along with the relationship. You can put such a field on the layout. It's convenient for quick picking of related records. It's not a good option if your relationship is intended to have a lot of linked records that can slow down loading of the detail view screen.\n\nExamples of link-multiple fields:\n\n* *Teams* field – most entities have this field;\n* *Contacts* field in *Opportunity*;\n* *Contacts* field in *Case*.\n\n#### Audited\n\nIf the parameter **Audited** is checked, then updates of the relationship will be logged in Stream.\n\n## Formula\n\n### Before-save custom script\n\nThis [formula](formula.md) script will be executed every time before a record is saved. This provides the ability to automatically set specific fields with values derived from calculation. In addition, some functions can perform actions, for example, record creation.\n\nTo edit the formula script for a specific entity type, follow Administration > Entity Manager > a needed entity type > Formula.\n\n!!! note\n\n    It can be reasonable to set fields that are supposed to be calculated by formula as read-only (Administration > Entity Manager > {Entity Type} > Fields).\n\nAn administrator can run *Recalculate Formula* action for specific records from the list view: select records (or all search results) > click *Actions* dropdown > click *Recalculate Formula*.\n\n### API before-save script\n\n*As of v7.5.*\n\nThis [formula](formula.md) script is called on create and update API requests, before the record is saved. See more [detail](api-before-save-script.md).\n\n## Copying customizations to another instance\n\nAll customizations made through Entity Manager are stored in the `custom/Espo/Custom` folder. You need to copy contents of this folder to another instance and then run rebuild (CLI command `php rebuild.php`).\n\n### Exporting to extension\n\nIt's also possible to export customization to an installable extension. On the Entity Manager page, from the dropdown next to *Create Entity* button.\n"
  },
  {
    "path": "docs/administration/extensions.md",
    "content": "# Managing extensions\n\n## Installing\n\nIn order to install EspoCRM extension (e.g. Advanced Pack):\n\n1. Login as an administrator.\n2. Go to Administration > Extensions.\n3. Upload your extension package (zip file).\n4. Click Install button.\n\n\n## Upgrading\n\nIn order to upgrade an already installed extension to a newer version:\n\n1. Download the new version of the needed extension.\n2. Log in as an administrator.\n3. Go to Administration > Extensions.\n4. Upload your new extension package (zip file) without uninstalling the already installed version.\n5. Click the **Install** button.\n\n!!! note\n\n    There's no need to install intermediate versions. Install just the latest one.\n\n## Uninstalling\n\nSteps to uninstall an extension:\n\n1. Login as an administrator.\n2. Go to Administration > Extensions.\n3. Find the needed extension on the list of available extensions.\n4. Click **Uninstall** from the dropdown.\n\n!!! note\n\n    Uninstalling an extension does not cause data loss (unless the developer deliberately added such a logic). You can install the extension again and continue using it. Though, if you run a hard rebuild after uninstalling, it will remove all custom database columns added by the extension but it won't remove custom tables.\n\n## Deleting\n\nWhen an extension is uninstalled, it is still available in the system. It can be completely deleted. Steps to delete an extension:\n\n1. Login as an administrator.\n2. Go to Administration > Extensions.\n3. Find the needed extension in the list of available extensions.\n4. Click **Remove** from the dropdown.\n\n## CLI commands\n\n### Installing & upgrading\n\n```\nphp command.php extension --file=\"path/to/extension/package.zip\"\n```\n\nSee more [commands](commands.md#extension).\n\n!!! note\n\n    In some cases, installing extensions via CLI is preferable, as usually PHP configuration for CLI is not as limited as for a web server.\n    For example, if a new version of an extension adds some database index, it can cause a timeout error when upgrading through the UI.\n"
  },
  {
    "path": "docs/administration/fields.md",
    "content": "# Fields\n\n## Field types\n\nThe list of field types available for creating:\n\n* [Varchar](#varchar) – a single-line text;\n* [Enum](#enum) – a selectbox, only one value can be selected;\n* [Text](#text) – a multiline text with markdown support;\n* [Date](#date) – date w/o time;\n* [Date-Time](#date-time) – date and time;\n* [Currency](#currency) – for currency values, a float number and currency code;\n* [Int](#int) – a whole number;\n* [Float](#float) – a number with a decimal part;\n* [Decimal](#decimal) – a decimal number with fixed-point precision;\n* [Boolean](#boolean) – a checkbox;\n* [Multi-Enum](#multi-enum) – a list of values, multiple values can be selected;\n* [Checklist](#checklist) – a list of checkboxes;\n* [Array](#array) – a list of values, similar to Multi-Enum field;\n* [Address](#address) – an address with street, city, state, postal code and country;\n* [Url](#url) – for storing links;\n* [Url-Multiple](#url-multiple) – for storing multiple links;\n* [Wysiwyg](#wysiwyg) – similar to Text field, but with HTML support;\n* [File](#file) – for file uploading;\n* [Image](#image) – for image uploading;\n* [Attachment-Multiple](#attachment-multiple) – for multiple file uploading;\n* [Number](#number) – an auto-incrementing number of string type with a possible prefix and specific length;\n* [Auto-increment](#auto-increment) – a generated read-only auto-incrementing integer number;\n* [Barcode](#barcode) – a barcode, can be printed to PDF.\n* [Foreign](#foreign) - a field of a related record. Read-only.\n\nField types not available for creating directly:\n\n* [Email](#email) – a set of email addresses;\n* [Phone](#phone) – a set of phone numbers;\n* [Link](#link) – a record related through *Belongs-To* (*many-to-one* or *one-to-one*) relationship;\n* [Link-Parent](#link-parent) – a record related through *Belongs-To-Parent* relationship; can be of different entity types;\n* [Link-Multiple](#link-multiple) – a set of records related through *Has-Many* relationship.\n\n## Common field parameters\n\n* Label – a name of the field displayed on the UI;\n* Required – whether the field is mandatory; user won't be able to save a record w/o filling the field;\n* Audited – field changes will be stored in stream and available in the Audit Log;\n* Read-only – a field value can't be specified, but can be calculated by formula or workflow rule;\n* Read-only After Create – a field value can be specified only when creating a record, after that the field will became read-only; \n* Default – a value pre-filled when creating a new record;\n* Disable Inline Edit – may be useful when using Dynamic Logic;\n* Tooltip Text – information about the field for users (Markdown is supported);\n* Not Lockable – if enabled, the field is not locked when the record is locked.\n\n!!! note\n    \n    For most fields, the default value is set as the database default value. Therefore, when you create a new field with a default value, the database system automatically applies this value to all existing records.\n\n!!! note\n\n    When the read-only parameter is enabled for a *link* or *link-multiple* field, it won't be possible to create a related record from the relationship panel. It happens because the ID of the current record is passed in the link field.\n\n\n## Dynamic Logic\n\nProvides the ability to make forms dynamic. It's possible to define conditions making certain fields visible, required or read-only. Conditions will be checked automatically when data in the form is changed.\n\nFor the *Enum*, *Array*, *Multi-Enum*, *Checklist* fields, it's possible to define different sets of options that will be available for the field depending on which condition is met. See more [here](dynamic-logic.md).\n\nAvailable items:\n\n* Conditions making field visible\n* Conditions making field required\n* Conditions making field read-only\n* Conditional options – for enum, multi-enum, checklist, array, varchar fields\n\n----\n\n## Varchar\n\nA single-line text.\n\nParameters:\n\n* Max-length – a max acceptable length of text;\n* Options – a pre-defined list of values for an autocomplete;\n* Pattern – a regular expression to check a field value against;\n* Copy to clipboard button.\n\n![Varchar](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/varchar.png)\n\n## Enum\n\nSelectbox, only one value can be selected.\n\nParameters:\n\n* Options – a list of values (key => label pairs); a color (style) for each value can be specified (applied when param *Display as Label* is enabled);\n* Options Reference – options from another field to re-use (as of v7.5);\n* Is Sorted – to sort a list alphabetically;\n* Display as Label – a value will be displayed as a label with color; a color for each option can be specified.\n\nIt's possible to define conditional options with Dynamic Logic.\n\n![Enum](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/enum.png)\n\n![Enum detail view](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/enum-detail.png)\n\n!!! note\n\n    An empty option can be used to support a null value. Usually, it's reasonable to have it first in the list.\n\n## Text\n\nA multiline text with markdown support.\n\nParameters:\n\n* Max-length – a max acceptable length of a text;\n* Disable Text Cut – if not checked, then long texts will be shortened and can be expanded (for the detail view mode);\n* Number of rows of textarea – a max number of rows before scroll bar appears (for the edit view mode);\n* Cut Height (px) – a max height of a text, if longer, then it will be cut (for the detail view mode);\n* Display raw text (no markdown) – to disable markdown support;\n* Preview – the ability to preview a Markdown text;\n* Attachment Field – an Attachment-Multiple field to connect the Text field with.\n\n![Text](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/text.png)\n\n![Text detail view](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/text-detail.png)\n\n## Date\n\nDate w/o time.\n\nParameters:\n\n* After (field) – a validation: a date value should be after a date value of a specified field;\n* Before (field) – a validation: a date value should be before a date value of a specified field;\n* Use Numeric Format – if not checked, then words 'today', 'yesterday', 'tomorrow' are in the detail view mode.\n\n![Date](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/date.png)\n\n![Date detail view](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/date-detail.png)\n\n## Date-Time\n\nDate and time.\n\nParameters:\n\n* After (field) – a validation: a date value should be after a date value of a specified field;\n* Before (field) – a validation: a date value should be before a date value of a specified field;\n* Use Numeric Format – if not checked, then words 'today', 'yesterday', 'tomorrow' are in the detail view mode;\n* Minutes Step – defines items displayed in the minutes dropdown (in the edit mode).\n\n![Date-Time](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/date-time.png)\n\n![Date-Time detail view](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/date-time-detail.png)\n\n## Currency\n\nA currency value. A float number with a currency code.\n\nParameters:\n\n* Min – a validation: min acceptable value; if empty, then no validation applied;\n* Max – a validation: max acceptable value; if empty, then no validation applied;\n* Only default currency – only one (default) currency will be available if enabled;\n* Disable Conversion – the currency conversion action won't change the currency of the field;\n* Decimal – use decimal data type (when precision is necessary) (as of v7.4).\n\n![Currency](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/currency.png)\n\n![Currency detail view](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/currency-detail.png)\n\n## Int\n\nA whole number.\n\nParameters:\n\n* Min – a validation: min acceptable value; if empty, then no validation applied;\n* Max – a validation: max acceptable value; if empty, then no validation applied;\n* Disable Formatting – if not checked, then a value is formatted with a thousand separator.\n\n## Float\n\nA number with a decimal part.\n\nParameters:\n\n* Min – a validation: min acceptable value; if empty, then no validation applied;\n* Max – a validation: max acceptable value; if empty, then no validation applied;\n* Decimal Places – how many numbers of decimal part to display in read mode.\n\n## Decimal\n\n*As of v9.3.0.*\n\nA decimal number with fixed point precision. In the application, the value is represented as string. In the database – as DECIMAL.\n\n* Min – a validation: min acceptable value; if empty, then no validation applied;\n* Max – a validation: max acceptable value; if empty, then no validation applied;\n* Decimal Places – how many numbers of decimal part to display in read mode.\n\n## Boolean\n\nA checkbox. Two possible values: true and false.\n\n![Boolean](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/bool.png)\n\n## Multi-Enum\n\nA list of values, multiple values can be selected. The list is ordered.\n\n![Multi-Enum](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/multi-enum.png)\n\n![Multi-Enum detail view](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/multi-enum-detail.png)\n\nParameters:\n\n* Options – a list of values (key => label pairs); a color (style) for each value can be specified (applied when param *Display as Label* is enabled);\n* Options Reference – options from another field to re-use (as of v7.5);\n* Is Sorted – to sort a list alphabetically;\n* Allow Custom Options – if checked, a user can add custom values (not defined by *Options* parameter) by typing text and pressing the enter key;\n* Max Item Count – a validation: how many items can be added;\n* Display as Label – values will be displayed as a label with color; a color for each option can be specified;\n* Display as List – each value will be displayed in a new line;\n* Pattern – a regular expression to check a field value against.\n\n\n## Checklist\n\nA list of checkboxes.\n\nParameters:\n\n* Options – a list of values (key => label pairs); a color (style) for each value can be specified (applied when param *Display as Label* is enabled);\n* Options Reference – options from another field to re-use (as of v7.5);\n* Is Sorted – to sort a list alphabetically;\n* Max Item Count – a validation: how many items can be checked;\n\n\n## Array\n\nA list of values, similar to Multi-Enum field.\n\nParameters:\n\n* Options – a list of values (key => label pairs); if no options specified, then a user will be able to add any options;\n* Options Reference – options from another field to re-use;\n* Empty string value is not allowed – if not checked, a user can add an empty string as an item;\n* Max Item Count – a validation: how many items can be added;\n* Display as List – each value will be displayed in a new line;\n* Items Editable – items can be edited; applicable only if no options are specified for the field; as of v9.2;\n* Pattern – a regular expression to check a field value against.\n\n![Array](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/array.png)\n\n## Address\n\nAn address with street, city, state, postal code and country.\n\n![Address](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/address.png)\n\n## Url\n\nFor storing links.\n\nParameters:\n\n* Max-length – a max acceptable length of text;\n* Require Protocol – if enabled, an URL must contain the protocol part (as of v10.0);\n* Strip – if checked, then a protocol part and trailing `/` will be stripped;\n* Copy to clipboard button.\n\n## Url-Multiple\n\n*As of v7.5.*\n\nFor storing multiple links.\n\nParameters:\n\n* Max Item Count – max number or items;\n* Strip – if checked, then a protocol part and trailing `/` will be stripped.\n\n## Wysiwyg\n\nSimilar to the Text field, but with HTML support.\n\nParameters:\n\n* Height (px) – a height of the field (in the edit view mode); if empty – then  height is flexible;\n* Min Height (px) – a min height of the field (in the edit view mode);\n* Use Iframe – if checked, then an HTML content will be placed in an IFRAME element.\n\n## File\n\nFor file uploading.\n\nParameters:\n\n* Source List – allows a user to get a file from another record (*Documents* source is available out-of-the-box);\n* Max File Size (Mb) – a validation;\n* Accept – which file types can be accepted; see [info](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers) about file types.\n\n\n## Image\n\nFor image uploading.\n\nParameters:\n\n* Preview Size – defines a size of an image displayed on the detail/list view;\n* Max File Size (Mb) – a validation;\n* Capture – Specifies which camera to use for capture of image data. Options: Empty, User or Environment. As of v10.0.0.\n  \n\n## Attachment-Multiple\n\nAllows to upload multiple files.\n\nParameters:\n\n* Source List – allows a user to get a file from another record (*Documents* source is available out-of-the-box);\n* Max File Size (Mb) – a validation;\n* Accept – which file types can be accepted; see [info](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers) about file types;\n* Preview Size – defines a size of an image displayed on the detail/list view.\n\n## Number\n\nAn auto-incrementing number of string type with a possible prefix and specific length.\n\nParameters:\n\n* Prefix – a text that will be preprended to a number;\n* Next Number – a number that will be applied to the next created record;\n* Pad Length – a length of the numeric part; if less, then will be padded with zero digits, e.g. `00001`;\n* Copy to clipboard button.\n\n![Number](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/fields/number.png)\n\n## Auto-increment\n\nA generated read-only auto-incrementing integer number.\n\n## Barcode\n\nA barcode. Can be printed to PDF.\n\nParameters:\n\n* Code Type – a type of barcode; supported types: CODE128, CODE128A, CODE128B, CODE128C, EAN13, EAN8, EAN5, EAN2, UPC, UPCE, ITF14, pharmacode, QRcode;\n* Last Character – for EAN13 type, often is `>`.\n\n## Foreign\n\nA field of a related record. Read-only.\n\nParameters:\n\n* Link – defines where the field will be taken from.\n* Field – a field of a related record;\n* Relate on Import – when importing, it will automatically relate a record with a matching foreign record.\n\n## Email\n\nA set of email addresses with their parameters: *Opted-out*, *Invalid*, *Primary*.\n\n## Phone\n\nA set of phone numbers with their parameters: *Type*, *Opted-out*, *Invalid*, *Primary*.\n\nParameters:\n\n* Type List – a list of types available for phone numbers (e.g. Home, Office).\n\n## Link\n\nA record related through *Belongs-To* (*many-to-one* or *one-to-one*) relationship.\n\nParameters:\n\n* Create Button – display *Create* button;\n* Autocomplete on empty input – show suggestions even if no characters are entered in the input.\n\n## Link-Parent\n\nA record related through *Belongs-To-Parent* relationship. Can be of different entity types.\n\nParameters:\n\n* Entity List – a list of entity types available to be related through the field;\n* Autocomplete on empty input – show suggestions even if no characters are entered in the input.\n\n## Link-Multiple\n\nA set of records related through *Has-Many* (*many-to-many* or *one-to-many*) relationship. Not all relationships have a link-multiple field. Only those do, where *Link-Multiple* parameter(s) is enabled.\n\nParameters:\n\n* Max Item Count – the max number of records;\n* Create Button – display *Create* button;\n* Autocomplete on empty input – show suggestions even if no characters are entered in the input.\n"
  },
  {
    "path": "docs/administration/file-storage.md",
    "content": "# File Storage\n\nBy default, all uploaded files (attachments) are stored in `data/upload` directory. EspoCRM is shipped with AWS S3 support.\nDevelopers can also add other providers by implementing `Espo\\Core\\FileStorage\\Storage` interface.\n\nWhen switching to an external file storage, it's recommended to disable caching for image thumbs by setting in `data/config.php`:\n\n```\n'thumbImageCacheDisabled' => true,\n```\n\n## AWS S3\n\nParameters need to be set in `data/config-internal.php`:\n\n```\n  'awsS3Storage' => [\n    'bucketName' => 'BUCKET_NAME',\n    'path' => 'OPTIONAL_PATH_WHERE_FILES_WILL_BE_STORED',\n    'credentials' => [\n      'key' => 'KEY',\n      'secret' => 'SECRET',\n    ],\n    'region' => 'YOUR_REGION',\n  ],\n```\n\nIn `data/config.php`:\n\n```\n  'defaultFileStorage' => 'AwsS3',\n```\n\nCredentials can be omitted, then they will be read from the environment.\n\nIt's possible to use non-AWS S3 endpoints with the `endpoint` parameter (as of v8.1). Then, for some providers, you also need to add the parameter `pathStyleEndpoint` set to *true* to use path styled endpoints. The `sendChunkedBody` boolean parameter set to *false* may be needed for some providers that do not support splitting content in chunks.\n\n## Moving existing attachments\n\nAfter setting up a file storage, all existing attachments will still be stored locally in `data/upload` directory. You can move them manually to the storage and then execute the following SQL query:\n\n```sql\nUPDATE `attachment` SET `storage` = '{StorageName}'\n```\n\nwhere *{StorageName}* is a name of the storage, e.g. `AwsS3`.\n"
  },
  {
    "path": "docs/administration/formula/array.md",
    "content": "# Formula > Functions > Array\n\n* [array\\includes](#arrayincludes)\n* [array\\push](#arraypush)\n* [array\\length](#arraylength)\n* [array\\at](#arrayat)\n* [array\\join](#arrayjoin)\n* [array\\indexOf](#arrayindexof)\n* [array\\removeAt](#arrayremoveat)\n* [array\\unique](#arrayunique)\n\n## array\\includes\n\n`array\\includes(LIST, VALUE)`\n\nReturns true if LIST contains VALUE. Can be used for Array and Multi-Enum fields.\n\n## array\\push\n\n`array\\push(LIST, VALUE1 [, VALUE2 ...])`\n\nAdds one or more elements to the end of an array and returns the new array.\n\n\n!!! warning\n\n    An array argument is not passed by reference. You need to re-assign the array to a function result.\n\n!!! example\n\n    ```\n    $list = array\\push($list, 'test');\n    ```\n\n!!! example\n\n    Adding values to a multi-enum field.\n\n    ```\n    someMultiEnumField = array\\push(someMultiEnumField, 'New Value 1', 'New Value 2');\n    ```\n\n!!! note\n\n    Alternatively, it's possible to use *[]* syntax: `$list[] = $value;`. As of v9.1.\n\n## array\\length\n\n`array\\length(LIST)`\n\nReturns the number of elements in LIST.\n\n!!! example\n\n    A number of items in multi-enum field.\n\n    ```\n    $number = array\\length(someMultiEnumField);\n    ```\n\n## array\\at\n\n`array\\at(LIST, INDEX)`\n\nReturns a value by INDEX.\n\n!!! note\n\n    Alternatively, it's possible to use *[]* syntax: `$value = $list[$index];`. As of v9.1.\n\n## array\\join\n\n`array\\join(LIST, SEPARATOR)`\n\nJoins array elements with a string separator. Returns a string. (as of v6.1.3)\n\n!!! example\n\n    ```\n    $string = array\\join($array, $separator);\n    ```\n\n## array\\indexOf\n\n`array\\indexOf(LIST, ELEMENT)`\n\nReturns a position of the ELEMENT in the LIST. Returns `null` if the ELEMENT not in the LIST. (as of v7.1)\n\n!!! example\n\n    ```\n    $index = array\\indexOf($idList, $someId);\n    ```\n\n## array\\removeAt\n\n`array\\removeAt(LIST, INDEX)`\n\nRemoves an element by the INDEX and returns a new array. (as of v7.1)\n\n!!! example\n\n    ```\n    $newArray = array\\removeAt($array, $index);\n    ```\n\n## array\\unique\n\n`array\\unique(LIST)`\n\nRemoves duplicates in the LIST and returns a new array. (as of v7.1)\n\n!!! example\n\n    ```\n    $newArray = array\\unique($array);\n    ```\n"
  },
  {
    "path": "docs/administration/formula/datetime.md",
    "content": "# Formula > Functions > Datetime\n\nDate and date-time values are represented as strings. E.g. `'2021-01-01'`, `'2021-01-01 10:00'`.\n\n* [datetime\\today](#datetimetoday)\n* [datetime\\now](#datetimenow)\n* [datetime\\format](#datetimeformat)\n* [datetime\\date](#datetimedate)\n* [datetime\\month](#datetimemonth)\n* [datetime\\year](#datetimeyear)\n* [datetime\\hour](#datetimehour)\n* [datetime\\minute](#datetimeminute)\n* [datetime\\dayOfWeek](#datetimedayofweek)\n* [datetime\\diff](#datetimediff)\n* [datetime\\addSeconds](#datetimeaddseconds)\n* [datetime\\addMinutes](#datetimeaddminutes)\n* [datetime\\addHours](#datetimeaddhours)\n* [datetime\\addDays](#datetimeadddays)\n* [datetime\\addWeeks](#datetimeaddweeks)\n* [datetime\\addMonths](#datetimeaddmonths)\n* [datetime\\addYears](#datetimeaddyears)\n* [datetime\\closest](#datetimeclosest)\n\n\n## datetime\\today\n\n`datetime\\today()`\n\nReturns a today's date (w/o time).\n\n## datetime\\now\n\n`datetime\\now()`\n\nReturns a current datetime.\n\n## datetime\\format\n\n`datetime\\format(VALUE, [TIMEZONE], [FORMAT])`\n\nConverts a date or datetime VALUE to a string formatted according to the application settings or a given timezone and ISO format. TIMEZONE and FORMAT can be omitted. If TIMEZONE is omitted, then the default timezone will be used. If FORMAT is omitted, then the default format will be used.\n\n!!! example\n\n    `datetime\\format(closeDate, 'America/New_York', 'MM/DD/YYYY')`\n\n    `datetime\\format(dateStart, 'America/New_York', 'MM/DD/YYYY hh:mma')`\n\n    `datetime\\format(dateStart, 'Europe/Amsterdam', 'DD/MM/YYYY HH:mm')`\n\n## datetime\\date\n\n`datetime\\date(VALUE, [TIMEZONE])`\n\nReturns date of the month (1-31). `0` if VALUE is empty. If TIMEZONE is omitted, then system timezone is used.\n\n## datetime\\month\n\n`datetime\\month(VALUE, [TIMEZONE])`\n\nReturns month (1-12). `0` if VALUE is empty. If TIMEZONE is omitted, then system timezone is used.\n\n## datetime\\year\n\n`datetime\\year(VALUE, [TIMEZONE])`\n\nReturns year. `0` if VALUE is empty. If TIMEZONE is omitted, then system timezone is used.\n\n## datetime\\hour\n\n`datetime\\hour(VALUE, [TIMEZONE])`\n\nReturns hour (0-23). `-1` if VALUE is empty. If TIMEZONE is omitted, then system timezone is used.\n\n## datetime\\minute\n\n`datetime\\minute(VALUE, [TIMEZONE])`\n\nReturns minute (0-59). `-1` if VALUE is empty. If TIMEZONE is omitted, then system timezone is used.\n\n## datetime\\dayOfWeek\n\n`datetime\\dayOfWeek(VALUE, [TIMEZONE])`\n\nReturns day of the week (0-6). `-1` if VALUE is empty. `0` - for Sunday. If TIMEZONE is omitted, then system timezone is used.\n\n## datetime\\diff\n\n`datetime\\diff(VALUE_1, VALUE_2, INTERVAL_TYPE)`\n\nReturns the difference between two dates or datetimes. INTERVAL_TYPE can be 'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Returns `null` if failure. The result will be negative if VALUE_1 < VALUE_2.\n\n## datetime\\addSeconds\n\n*As of v9.2.0.*\n\n`datetime\\addMinutes(VALUE, SECONDS)`\n\nAdds SECONDS to a datetime VALUE. SECONDS can be negative. Returns a modified STRING value.\n\n## datetime\\addMinutes\n\n`datetime\\addMinutes(VALUE, MINUTES)`\n\nAdds MINUTES to a datetime VALUE. MINUTES can be negative. Returns a modified STRING value.\n\n!!! example\n\n    `$modifiedValue = datetime\\addMinutes('2021-01-01 00:00', 10)`\n\n## datetime\\addHours\n\n`datetime\\addHours(VALUE, HOURS)`\n\nAdds HOURS to a datetime VALUE. HOURS can be negative. Returns a modified STRING value.\n\n## datetime\\addDays\n\n`datetime\\addDays(VALUE, DAYS)`\n\nAdds DAYS to a date or datetime VALUE. DAYS can be negative.\n\n!!! example\n\n    `datetime\\addDays(dateStart, 1)`\n\n## datetime\\addWeeks\n\n`datetime\\addWeeks(VALUE, WEEKS)`\n\nAdds WEEKS to a date or datetime VALUE. WEEKS can be negative. Returns a modified STRING value.\n\n!!! example\n\n    `datetime\\addWeeks(dateStart, 4)`\n\n## datetime\\addMonths\n\n`datetime\\addMonths(VALUE, MONTHS)`\n\nAdds MONTHS to a date or datetime VALUE. MONTHS can be negative. Returns a modified STRING value.\n\n!!! example\n\n    `datetime\\addMonths(dateStart, 1)`\n\n## datetime\\addYears\n\n`datetime\\addYears(VALUE, YEARS)`\n\n!!! example\n\n    `datetime\\addYears(dateStart, 1)`\n\nAdds YEARS to a date or datetime VALUE. YEARS can be negative. Returns a modified STRING value.\n\n## datetime\\closest\n\n`datetime\\closest(VALUE, TYPE, TARGET, [IS_PAST], [TIMEZONE])`\n\nReturns the closest date or datetime to VALUE based on passed arguments.\n\nTYPE can be one of the following values: 'time', 'minute', 'hour', 'date', 'month', 'dayOfWeek'. TARGET is an integer value or a string value. \nIS_PAST means to find the closest in the past. If TIMEZONE is omitted, then the default timezone is used.\n\n!!! example\n\n    `datetime\\closest(datetime\\now(), 'time', '20:00')` Will return the closest datetime value in the future with 20:00 time.\n\n    `datetime\\closest('2017-11-20', 'date', 1, true)` Will return `2017-11-01`, the first day of the month.\n\n    `datetime\\closest(datetime\\now(), 'dayOfWeek', 1)` Will return the next Monday (the beginning of the day).\n"
  },
  {
    "path": "docs/administration/formula/entity.md",
    "content": "# Formula > Functions > Entity\n\nFunctions of the *Entity* group operate with a target record. There can be only one target record available in formula-script context.\nFor *Before Update Script*, the target record is the record that is currently updated. For Workflow's *Create Record* action,\nthe target record is the record is being created. For Workflow's conditions, the target record is the target record of the workflow rule.\n\n* [entity\\isNew](#entityisnew)\n* [entity\\isAttributeChanged](#entityisattributechanged)\n* [entity\\isAttributeNotChanged](#entityisattributenotchanged)\n* [entity\\attribute](#entityattribute)\n* [entity\\setAttribute](#entitysetattribute)\n* [entity\\clearAttribute](#entityclearattribute)\n* [entity\\attributeFetched](#entityattributefetched)\n* [entity\\addLinkMultipleId](#entityaddlinkmultipleid)\n* [entity\\hasLinkMultipleId](#entityhaslinkmultipleid)\n* [entity\\removeLinkMultipleId](#entityremovelinkmultipleid)\n* [entity\\setLinkMultipleColumn](#entitysetlinkmultiplecolumn)\n* [entity\\isRelated](#entityisrelated)\n* [entity\\sumRelated](#entitysumrelated)\n* [entity\\countRelated](#entitycountrelated)\n* [entity\\getLinkColumn](#entitygetlinkcolumn)\n\n\n## entity\\isNew\n\n`entity\\isNew()`\n\nReturns TRUE if the entity is new (being created) and FALSE if not (being updated).\n\n## entity\\isAttributeChanged\n\n`entity\\isAttributeChanged(ATTRIBUTE)`\n\nReturns TRUE if ATTRIBUTE of the record was changed.\n\n!!! example\n\n    `entity\\isAttributeChanged('status')`\n\n## entity\\isAttributeNotChanged\n\n`entity\\isAttributeNotChanged(ATTRIBUTE)`\n\nReturn TRUE if ATTRIBUTE of the record was not changed.\n\n## entity\\attribute\n\n`entity\\attribute(ATTRIBUTE)`\n\nAn ATTRIBUTE value of a target record. It's also possible to fetch an attribute of a related record.\n\n`$test = entity\\attribute('name')` is equivalent to `$test = name`.\n\n!!! example\n\n    `entity\\attribute('assignedUserId')`\n\n    `entity\\attribute('account.name')`\n\n## entity\\setAttribute\n\n`entity\\setAttribute(ATTRIBUTE, VALUE)`\n\nSet an ATTRIBUTE with a VALUE.\n\n`entity\\setAttribute('stage', 'Closed Won')` is equivalent to `stage = 'Closed Won'`.\n\n!!! example\n\n    `entity\\setAttribute('stage', 'Closed Won')`\n\n## entity\\clearAttribute\n\n`entity\\clearAttribute(ATTRIBUTE)`\n\n*As of v8.2.*\n\nClear an ATTRIBUTE.\n\n!!! example\n\n    `entity\\clearAttribute('stage')`\n\n## entity\\attributeFetched\n\n`entity\\attributeFetched(ATTRIBUTE)`\n\nAn ATTRIBUTE value that was set when a target record was fetched from database. Before it was modified.\n\n!!! example\n\n    `entity\\attributeFetched('assignedUserId')`\n\nNote: Should not be used in workflow and BPM actions, use `workflow\\targetEntity\\attributeFetched` instead.\n\n## entity\\addLinkMultipleId\n\n`entity\\addLinkMultipleId(LINK, ID)`\n\nAdds ID to Link Multiple field.\n\n`entity\\addLinkMultipleId(LINK, ID_LIST)`\n\nAdds the list of ids.\n\n!!! example\n\n    `entity\\addLinkMultipleId('teams', 'someTeamId')`\n\nAdd 'someTeamId' to 'teams' field.\n\n## entity\\hasLinkMultipleId\n\n`entity\\hasLinkMultipleId(LINK, ID)`\n\nChecks whether Link Multiple field has specific ID.\n\n## entity\\removeLinkMultipleId\n\n`entity\\removeLinkMultipleId(LINK, ID)`\n\nRemoves a specific ID from the Link Multiple field.\n\n## entity\\setLinkMultipleColumn\n\n`entity\\setLinkMultipleColumn(LINK, ID, COLUMN, VALUE)`\n\n*As of v7.4.*\n\nSets a column value in a link-multiple field.\n\n## entity\\isRelated\n\n`entity\\isRelated(LINK, ID)`\n\nChecks whether a target entity is related with another entity represented by LINK and ID.\n\n## entity\\sumRelated\n\n`entity\\sumRelated(LINK, FIELD, [FILTER])`\n\nSums related records by a specified FIELD with an optional FILTER. Returns a *float* value.\n\n!!! example\n\n    `entity\\sumRelated('opportunities', 'amountConverted', 'won')`\n\nFILTER is a name of a filter pre-defined in the system. It's also possible to apply a [list report](../../user-guide/reports.md) as a filter. More [info](../formula.md#filter).\n\n## entity\\countRelated\n\n`entity\\countRelated(LINK, [FILTER])`\n\nReturns a number of related records with an optional FILTER applied.\n\n!!! example\n\n    `entity\\countRelated('opportunities', 'open')`\n\nIt's possible to apply a [list report](../../user-guide/reports.md) as a filter. More [info](../formula.md#filter).\n\n## entity\\getLinkColumn\n\n`entity\\getLinkColumn(LINK, ID, COLUMN)`\n\nFetches a relationship column value.\n\n!!! example\n\n    `entity\\getLinkColumn('targetLists', 'TARGET_LIST_ID', 'optedOut')`\n"
  },
  {
    "path": "docs/administration/formula/env.md",
    "content": "# Formula > Functions > Env\n\n## env\\userAttribute\n`env\\userAttribute(ATTRIBUTE)`\n\nReturns ATTRIBUTE of the current user.\n\n!!! example\n\n    ```\n    env\\userAttribute('id') // an ID of the current user\n    ```\n"
  },
  {
    "path": "docs/administration/formula/exception.md",
    "content": "# Formula > Functions > Exception\n\n* [exception\\throwInvalid](#exceptionthrowinvalid)\n\n## exception\\throwInvalid\n\n`exception\\throwInvalid([MESSAGE])`\n\n*As of v10.0.*\n\nThrows a validation exception. To be used within a Before-save script (not API before-save script).\nCan be used for internal validation that is performed every time an entity is saved.\n\nThe error message (passed as the first parameter) is not displayed to the user, but logged.\n\n!!! example\n\n    ```\n    if (!assignedUserId) {\n        exception\\throwInvalid(\"No assigned user.\");\n    }\n    ```\n"
  },
  {
    "path": "docs/administration/formula/ext.md",
    "content": "# Formula > Functions > Ext\n\n* [ext\\account\\findByEmailAddress](#extaccountfindbyemailaddress)\n* [ext\\currency\\convert](#extcurrencyconvert)\n* [ext\\email\\send](#extemailsend)\n* [ext\\email\\applyTemplate](#extemailapplytemplate)\n* [ext\\markdown\\transform](#extmarkdowntransform)\n* [ext\\sms\\send](#extsmssend)\n* [ext\\pdf\\generate](#extpdfgenerate)\n* [ext\\user\\sendAccessInfo](#extusersendaccessinfo)\n* [ext\\calendar\\userIsBusy](#extcalendaruserisbusy)\n* [ext\\acl\\checkEntity](#extaclcheckentity)\n* [ext\\acl\\checkScope](#extaclcheckscope)\n* [ext\\acl\\getLevel](#extaclgetlevel)\n* [ext\\acl\\getPermissionLevel](#extaclgetpermissionlevel)\n* [ext\\oauth\\getAccessToken](#extoauthgetaccesstoken)\n* [ext\\appSecret\\get](#extappsecretget)\n\n## ext\\account\\findByEmailAddress\n\n`ext\\account\\findByEmailAddress(EMAIL_ADDRESS)`\n\nFinds an account by an email address. If no full match found, then tries to find by domain name.\nFree email provider domains are ignored. Returns ID or null.\n\n## ext\\currency\\convert\n\n`ext\\currency\\convert(AMOUNT, FROM_CODE, [TO_CODE])`\n\n*As of v7.4.*\n\nConverts a currency amount from one currency code (FROM_CODE) to another currency code (TO_CODE). If TO_CODE is omitted, then\nthe system default currency is used. Returns an amount represented as string.\n\n!!! example\n\n    ```\n    $convertedValueString = ext\\currency\\convert(amount, amountCurrency);\n    $convertedValue = number\\parseFloat($convertedValue);\n    ```\n\n## ext\\email\\send\n\n`ext\\email\\send(EMAIL_ID)`\n\nSends an email. EMAIL_ID is an ID of an email record. Returns TRUE if sent, false if not sent.\n\nIf *from* address is not set in the email, then the system email address will be used. If there's match between *from* address and \nthe address of some group email account, then SMTP setting of the group email account will be used.\n\n!!! example\n\n    ```\n    $id = record\\create(\n        'Email',\n        'from', 'from-address@test.com',\n        'to', 'to-address@test.com',\n        'subject', 'Test from formula',\n        'body', 'Hi,\\n\\nThis is a test.',\n        'isHtml', false,\n        'status', 'Sending'\n    );\n    ext\\email\\send($id);\n    ```\n\nMultiple email addresses can be specified by using a `;` character as a delimiter.\n\n## ext\\email\\applyTemplate\n\n`ext\\email\\applyTemplate(EMAIL_ID, EMAIL_TEMPLATE_ID, [PARENT_TYPE, PARENT_ID])`\n\nApplies an email template to an existing email record. Parent record can be passed optionally.\n\n!!! example\n\n    ```\n    $emailId = record\\create(\n        'Email',\n        'to', 'to-address@test.com',\n        'status', 'Draft',\n        'parentId', entity\\attribute('id'),\n        'parentType', 'Case'\n    );\n    ext\\email\\applyTemplate($emailId, 'some-email-template-id');\n    ext\\email\\send($emailId);\n    ```\n\n## ext\\markdown\\transform\n\n*As of v9.0.*\n\n`ext\\markdown\\transform(STRING)`\n\nTransforms a markdown text to an HTML. Returns STRING.\n\n## ext\\sms\\send\n\n*As of v7.0.*\n\n`ext\\sms\\send(SMS_ID)`\n\nSends an SMD. SMS_ID is an ID of an SMS record. Returns TRUE if sent, false if not sent.\n\n!!! example\n\n    ```\n    $smsId = record\\create(\n        'Sms',\n        'to', '+1 000 111 222',\n        'body', 'This is a test.'\n    );\n\n    ext\\sms\\send($smsId);\n    ```\n\nIf *from* address is not set in the SMS, then the system SMS from number will be used.\n\nThe extension with SMS providers can be downloaded [here](https://github.com/espocrm/ext-sms-providers/releases).\n\n## ext\\pdf\\generate\n\n`ext\\pdf\\generate(ENTITY_TYPE, ENTITY_ID, TEMPLATE_ID, [FILENAME])`\n\nGenerates PDF file and returns attachment ID. If failed, then returns NULL. TEMPLATE_ID is an ID of PDF template.\n\n!!! example\n\n    ```\n    $attachmentId = ext\\pdf\\generate(\n        'Lead',\n        entity\\attribute('id'),\n        'pdf-template-id',\n        'test.pdf'\n    );\n\n    $emailId = record\\create('Email',\n        'subject', 'Test PDF',\n        'body', 'PDF is attached',\n        'to', entity\\attribute('emailAddress'),\n        'attachmentsIds', list($attachmentId)\n    );\n\n    ext\\email\\send($emailId);\n    ```\n\nNote, that this won't work for new records in before-create script because a record is not yet created. It will work in Workflows.\n\n## ext\\user\\sendAccessInfo\n\n`ext\\user\\sendAccessInfo(USER_ID)`\n\nSend an email with access info to a specific user (via email). A user password will be reset. The user will be promted to specify their \nnew password. This function is useful when creating a new user via formula. (as of v7.1)\n\n!!! example\n\n    ```\n    $userId = record\\create(\n        'User',\n        'userName', $userName,\n        'firstName', $firstName,\n        'lastName', $lastName,\n        'emailAddress', $emailAddress,\n        'type', 'portal',\n        'portalsIds', list($portalId)\n    );\n\n    ext\\user\\sendAccessInfo($userId);\n    ```\n    \n## ext\\calendar\\userIsBusy\n\n*As of v7.5.*\n\n`ext\\calendar\\userIsBusy(USER_ID, FROM, TO, [ENTITY_TYPE, ID])`\n\nReturns TRUE if a user is has calendar activities within a given range. FROM and TO should be date-time strings.\n\nIf ENTITY_TYPE and ID specified, then this record will be ignored when checking. Useful when editing an existing record.\n\n!!! example\n\n    ```\n    if (entity\\isNew() && ext\\calendar\\userIsBusy(assignedUserId, dateStart, dateEnd)) {\n        // throw exception\n    }\n    ```\n\n## ext\\acl\\checkEntity\n\n*As of v8.3.*\n\n`ext\\acl\\checkEntity(USER_ID, ENTITY_TYPE, ID, [ACTION])`\n\nReturns TRUE if a user has access to an entity. Optional ACTION should be one of the values: Create, Read, Edit, Delete, Stream.\n\n\n## ext\\acl\\checkScope\n\n*As of v8.3.*\n\n`ext\\acl\\checkScope(USER_ID, SCOPE, [ACTION])`\n\nReturns TRUE if a user has access to a SCOPE. Optional ACTION should be one of the values: Create, Read, Edit, Delete, Stream.\n\n\n## ext\\acl\\getLevel\n\n*As of v8.3.*\n\n`ext\\acl\\getLevel(USER_ID, SCOPE, ACTION)`\n\nReturns an access level. ACTION should be one of the values: Create, Read, Edit, Delete, Stream.\n\n## ext\\acl\\getPermissionLevel\n\n*As of v8.3.*\n\n`ext\\acl\\getPermissionLevel(USER_ID, PERMISSION)`\n\nReturns a permission level.\n\n## ext\\oauth\\getAccessToken\n\n*As of v9.1.0.*\n\n`ext\\oauth\\getAccessToken(ACCOUNT_ID)`\n\nGet an OAuth access token for a specific OAuth Account. The ID of OAuth Account record can be obtained for its URL.\n\n## ext\\appSecret\\get\n\n*As of v9.2.3.*\n\n`ext\\appSecret\\get($secretName)`\n\nGet an App Secret.\n"
  },
  {
    "path": "docs/administration/formula/general.md",
    "content": "# Formula > Functions > General\n\n* [list](#list)\n* [ifThenElse](#ifthenelse)\n* [ifThen](#ifthen)\n\n## list\n\n`list(VALUE-1 [, ... VALUE-N])` \n\nReturns array. Values are passed as arguments of the function.\n\n!!! example\n\n    ```\n    $list = list(0, 1, 2); // will return array [0, 1, 2]\n    ```\n\nUseful to create an array for link-multiple IDs.\n\n!!! example\n\n    ```\n    teamsIds = list($teamId) // `['team-id']`\n    ```\n\n## ifThenElse\n\n`ifThenElse(CONDITION, CONSEQUENT, ALTERNATIVE)`\n\nIf CONDITION is met, then return CONSEQUENT. If not, then return ALTERNATIVE.\n\n!!! example\n\n    ```\n    $value = ifThenElse(\n        $someVariable == 'someValue', // if condition is true\n        'one value', // return this value\n        'another value' // otherwise, this\n    )\n    ```\n\n## ifThen\n\n`ifThen(CONDITION, CONSEQUENT)`\n\nIf CONDITION is met, then return CONSEQUENT. Otherwise, return NULL.\n\n!!! example\n\n    ```\n    ifThen(\n        $someVariable == 'someValue', // if condition is true\n        $anotherVariable = 1, // do this\n    )\n    ```\n"
  },
  {
    "path": "docs/administration/formula/json.md",
    "content": "# Formula > Functions > JSON\n\n* [json\\retrieve](#jsonretrieve)\n* [json\\encode](#jsonencode)\n\n## json\\retrieve\n\n`json\\retrieve(JSON, [PATH])`\n\nRetrieves a specific attribute from a JSON string. PATH is a string, items are separated by dots. (as of v6.0)\n\nIf PATH is omitted, it will return the whole JSON parsed (as of v8.0.4).\n\n!!! example\n\n    Retrieving *id* from `{\"id\": \"SOME_ID\"}`:\n\n    ```\n    $value = json\\retrieve($someJsonString, 'id');\n    ```\n\n!!! example\n\n    Retrieving *id* from `[{\"id\": \"SOME_ID\"}]`:\n\n    ```\n    $value = json\\retrieve($someJsonString, '0.id');\n    ```\n\n## json\\encode\n\n`json\\encode(VALUE)`\n\nEncodes a VALUE to a json string. (as of v7.1)\n"
  },
  {
    "path": "docs/administration/formula/language.md",
    "content": "# Formula > Functions > Language\n\n* [language\\translate](#languagetranslate)\n* [language\\translateOption](#languagetranslateoption)\n\n## language\\translate\n\n`language\\translate(LABEL, [CATEGORY, SCOPE])`\n\nTranslates a label to the language set as default. (as of v6.0)\n\n!!! example\n\n    ```\n    language\\translate('passwordWillBeSent', 'messages', 'User')\n    ```\n\n## language\\translateOption\n\n`language\\translateOption(OPTION, FIELD, [SCOPE])`\n\nTranslates an option of a specific field to the language set as default. The field can be of the following types: Enum, Multi-enum, Checklist, \nArray, Varchar. (as of v6.0)\n\n!!! example\n\n    ```\n    language\\translateOption('Customer', 'type', 'Account')\n    ```\n"
  },
  {
    "path": "docs/administration/formula/log.md",
    "content": "# Formula > Functions > Log\n\n*As of v8.3.*\n\n* [log\\info](#loginfo)\n* [log\\notice](#lognotice)\n* [log\\warning](#logwarning)\n* [log\\error](#logerror)\n\n## log\\info\n\n`log\\info(MESSAGE, [CONTEXT])`\n\nLog a string MESSAGE with the INFO level. An optional CONTEXT should be an object.\n\n## log\\notice\n\n`log\\notice(MESSAGE, [CONTEXT])`\n\nLog a string MESSAGE with the NOTICE level. An optional CONTEXT should be an object.\n\n## log\\warning\n\n`log\\warning(MESSAGE, [CONTEXT])`\n\nLog a string MESSAGE with the WARNING level. An optional CONTEXT should be an object.\n\n## log\\error\n\n`log\\error(MESSAGE, [CONTEXT])`\n\nLog a string MESSAGE with the ERROR level. An optional CONTEXT should be an object.\n"
  },
  {
    "path": "docs/administration/formula/number.md",
    "content": "# Formula > Functions > Number\n\n* [number\\format](#numberformat)\n* [number\\abs](#numberabs)\n* [number\\power](#numberpower)\n* [number\\round](#numberround)\n* [number\\floor](#numberfloor)\n* [number\\ceil](#numberceil)\n* [number\\randomInt](#numberrandomint)\n* [number\\parseInt](#numberparseint)\n* [number\\parseFloat](#numberparsefloat)\n\n## number\\format\n\n`number\\format(VALUE, [DECIMALS], [DECIMAL_MARK], [THOUSAND_SEPARATOR])`\n\nConverts a numeric VALUE into a string formatted according to a specific format or default application settings. If DECIMALS, DECIMAL_MARK or THOUSAND_SEPARATOR are omitted, then system defaults are used.\n\n!!! example\n\n    `number\\format(2.666667, 2)` – results 2.67;\n\n    `number\\format(1000, 2)` – results 1,000.00;\n\n    `number\\format(10.1, 0)` – results 10.\n\n\n## number\\abs\n\n`number\\abs(VALUE)`\n\nAbsolute value. Returns null if VALUE is not numeric.\n\n## number\\power\n\n`number\\power(VALUE, EXP)`\n\nRaising VALUE to EXP. VALUE and EXP should be int or float. Returns int or float. (as of v8.2)\n\n## number\\round\n\n`number\\round(VALUE, PRECISION)`\n\nReturns the rounded value of VALUE to specified PRECISION (number of digits after the decimal point). PRECISION can also be negative or zero (default).\n\n## number\\floor\n\n`number\\floor(VALUE)`\n\nReturns the next lowest integer value by rounding down the value if necessary.\n\n## number\\ceil\n\n`number\\ceil(VALUE)`\n\nReturns the next highest integer value by rounding up the value if necessary.\n\n## number\\randomInt\n\n`number\\randomInt([MIN, MAX])`\n\nGenerates a cryptographic random integer between specified MIN and MAX. If MIN is omitted, then `0` is used.\n\n## number\\parseInt\n\n`number\\parseInt(STRING)`\n\nConverts a string to an integer number. (as of v7.1)\n\n## number\\parseFloat\n\n`number\\parseFloat(STRING)`\n\nConverts a string to a float number. (as of v7.1)\n"
  },
  {
    "path": "docs/administration/formula/object.md",
    "content": "# Formula > Functions > Object\n\n* [object\\create](#objectcreate)\n* [object\\get](#objectget)\n* [object\\set](#objectset)\n* [object\\clear](#objectclear)\n* [object\\has](#objecthas)\n* [object\\cloneDeep](#objectclonedeep)\n\n## object\\create\n\n`object\\create()`\n\nCreates and returns an empty object (key-value map).\n\n## object\\get\n\n`object\\get(OBJECT, KEY)`\n\nRetrieves a value by a KEY from an OBJECT. Returns NULL if KEY is not set.\n\n!!! note\n\n    Alternatively, it's possible to use *[]* syntax: `$value = $object['key'];`. As of v9.1.\n\n## object\\set\n\n`object\\set(OBJECT, KEY, VALUE)`\n\nSets a value by a KEY.\n\n!!! note\n\n    Alternatively, it's possible to use *[]* syntax: `$object['key'] = $value;`. As of v9.1.\n\n!!! example\n\n    ```\n    $object = object\\create();\n    object\\set($object, 'key', 'some-value');\n    ```\n\n## object\\clear\n\n`object\\clear(OBJECT, KEY)`\n\nUnsets a value by a KEY.\n\n!!! example\n\n    ```\n    object\\clear($object, 'some-key');\n    ```\n\n## object\\has\n\n`object\\has(OBJECT, KEY)`\n\nChecks whether an OBJECT has a value set by a KEY. Returns a boolean.\n\n\n## object\\cloneDeep\n\n`object\\cloneDeep(OBJECT)`\n\nDeep clones an OBJECT. (as of v7.1)\n"
  },
  {
    "path": "docs/administration/formula/password.md",
    "content": "# Formula > Functions > Password\n\n## password\\generate\n\n`password\\generate()`\n\nGenerates and returns a password.\n\n## password\\hash\n\n`password\\hash(PASSWORD)`\n\nHashes a password. You need to hash the password before setting the *password* field for a *User*.\n\n!!! example\n\n    ```\n    $password = password\\generate();\n    $hash = password\\hash($password);\n    ```\n"
  },
  {
    "path": "docs/administration/formula/record.md",
    "content": "# Formula > Functions > Record\n\n* [record\\exists](#recordexists)\n* [record\\count](#recordcount)\n* [record\\findOne](#recordfindone)\n* [record\\findMany](#recordfindmany)\n* [record\\findRelatedOne](#recordfindrelatedone)\n* [record\\findRelatedMany](#recordfindrelatedmany)\n* [record\\attribute](#recordattribute)\n* [record\\fetch](#recordfetch)\n* [record\\relate](#recordrelate)\n* [record\\unrelate](#recordunrelate)\n* [record\\create](#recordcreate)\n* [record\\update](#recordupdate)\n* [record\\delete](#recorddelete)\n* [record\\relationColumn](#recordrelationcolumn)\n* [record\\updateRelationColumn](#recordupdaterelationcolumn)\n\n## record\\exists\n\n`record\\exists(ENTITY_TYPE, KEY1, VALUE1, [KEY2, VALUE2 ...])`\n\nCheck whether a record with specified criteria exists.\n\n`record\\exists(ENTITY_TYPE, [FILTER])`\n\nWith filter applied. As of v9.2. More [info](../formula.md#filter) about filters. \n\n!!! examples\n\n    `record\\exists('Lead', 'emailAddress=', fromAddress)`\n\n    `record\\exists('Lead', 'status=', list('Assigned', 'In Process'))`\n    \n    `record\\exists('Lead', 'body*', '%word%')`\n    \nAvailable operators: `=`, `!=`, `>`, `<`, `>=`, `<=`, `*` (LIKE operator), `!*`. Other querying record functions also support these operators.\n\n## record\\count\n\n`record\\count(ENTITY_TYPE, KEY1, VALUE1, [KEY2, VALUE2 ...])`\n\nReturns a count of records with specified criteria.\n\n`record\\count(ENTITY_TYPE, [FILTER])`\n\nReturns a count of records with an optional FILTER applied. More [info](../formula.md#filter) about filters.\n\n!!! examples\n\n    `record\\count('Opportunity', 'accountId=', id, 'stage=', 'Closed Won')`\n\n    `record\\count('Opportunity', 'amountConverted>', 1000)`\n\n    `record\\count('Opportunity', 'open')`\n\n    `record\\count('Lead', 'status=', list('Assigned', 'In Process'))`\n\nFILTER is a name of a primary filter pre-defined in the system. It's also possible to apply a [list report](../../user-guide/reports.md) as a filter.\nMore [info](../formula.md#filter).\n\n## record\\findOne\n\n`record\\findOne(ENTITY_TYPE, ORDER_BY, ORDER, [KEY1, VALUE1, KEY2, VALUE2 ...])`\n\nReturns a first found ID of a record that matches specific criteria.\n\n`record\\findOne(ENTITY_TYPE, ORDER_BY, ORDER, [FILTER])` Returns a first found ID of a record with an optional FILTER applied.\n\n!!! examples\n\n    `record\\findOne('Opportunity', 'createdAt', 'desc', 'accountId=', id, 'stage=', 'Closed Won')`\n\n    `record\\findOne('Opportunity', 'createdAt', 'desc', 'open')`\n\n    `record\\findOne('AppSecret', null, null, 'name', 'SECRET_NAME')`\n\n## record\\findMany\n\n*As of v8.0*.\n\n`record\\findMany(ENTITY_TYPE, LIMIT, ORDER_BY, ORDER, [KEY1, VALUE1, KEY2, VALUE2 ...])`\n\nReturns an array of IDs of records that match specific criteria.\n\n`record\\findMany(ENTITY_TYPE, LIMIT, ORDER_BY, ORDER, [FILTER])` With an optional FILTER applied.\n\n!!! examples\n\n    `record\\findMany('Opportunity', 10, 'createdAt', 'desc', 'accountId=', id, 'stage=', 'Closed Won')`\n\n    `record\\findMany('Opportunity', 5, 'createdAt', 'desc', 'open')`\n    \nORDER_BY and ORDER can be null.\n\nFILTER is a name of a primary filter pre-defined in the system. It's also possible to apply a [list report](../../user-guide/reports.md) as a filter.\nMore [info](../formula.md#filter).\n\n## record\\findRelatedOne\n\n`record\\findRelatedOne(ENTITY_TYPE, ID, LINK, [ORDER_BY, ORDER, KEY1, VALUE1, KEY2, VALUE2 ...])`\n\nReturns a first found ID of a related record that matches specific criteria.\n\n`record\\findRelatedOne(ENTITY_TYPE, ID, LINK, [ORDER_BY, ORDER, FILTER])`\n\nReturns a first found ID of a related record with an optional FILTER applied.\n\nIf NULL is passed for ORDER_BY and ORDER then a default order will be applied.\n\n!!! examples\n\n    `record\\findRelatedOne('Account', accountId, 'opportunities', 'createdAt', 'desc', 'stage=', 'Closed Won')`\n\n    `record\\findRelatedOne('Account', accountId, 'opportunities', 'createdAt', 'desc', 'open')`\n\nFILTER is a name of a filter pre-defined in the system. It's also possible to apply a [list report](../../user-guide/reports.md) as a filter.\nMore [info](../formula.md#filter).\n\n## record\\findRelatedMany\n\n`record\\findRelatedMany(ENTITY_TYPE, ID, LINK, LIMIT, [ORDER_BY, ORDER, KEY1, VALUE1, KEY2, VALUE2 ...])`\n\nReturns an array of IDs of a related record that matches specific criteria. LIMIT is the max number of record.\n\n`record\\findRelatedMany(ENTITY_TYPE, ID, LINK, LIMIT, [ORDER_BY, ORDER, FILTER])`\n\nReturns an array of IDs of a related record with an optional FILTER applied.\n\nIf NULL is passed for ORDER_BY and ORDER then a default order will be applied.\n\n!!! examples\n\n    `record\\findRelatedMany('Account', accountId, 'opportunities', 10, 'createdAt', 'desc', 'stage=', 'Closed Won')`\n\n    `record\\findRelatedMany('Account', accountId, 'opportunities', 3, 'createdAt', 'desc', 'open')`\n\nFILTER is a name of a filter pre-defined in the system. It's also possible to apply a [list report](../../user-guide/reports.md) as a filter. More [info](../formula.md#filter).\n\nThis function can be utilized for copying related records from one record to another. Example:\n\n```\n// copy teams from account to email\n$ids = record\\findRelatedMany('Account', $accountId, 'teams', 10);\nrecord\\relate('Email', $emailId, 'teams', $ids);\n```\n\n## record\\attribute\n\n`record\\attribute(ENTITY_TYPE, ID, ATTRIBUTE)`\n\nReturns an attribute value of a specific record.\n\n!!! examples\n\n    `record\\attribute('Opportunity', $opportunityId, 'amountConverted')`\n\n    `record\\attribute('Opportunity', $opportunityId, 'teamsIds')`\n\nBy utilizing this function along with *record\\findOne*, it's possible to fetch attribute values of any record in the system.\n\n## record\\fetch\n\n*As of v7.5.*\n\n`record\\fetch(ENTITY_TYPE, ID)`\n\nFetches record attributes into an object. Returns NULL if a record does not exists.\n\n!!! example\n\n    ```\n    $o = record\\fetch('Account', $accountId);\n\n    if ($o) {\n        $name = object\\get($o, 'name');\n    }\n    ```\n\n## record\\relate\n\nRelate two records:\n\n`record\\relate(ENTITY_TYPE, ID, LINK, FOREIGN_ID)`\n\nRelate a record with multiple records (passed as an array of IDs):\n\n`record\\relate(ENTITY_TYPE, ID, LINK, LIST_OF_IDS)`\n\nRelate with column data (as of v9.3.):\n\n`record\\relate(ENTITY_TYPE, ID, LINK, FOREIGN_ID, COLUMN_DATA)`\n\n\n!!! examples\n\n    `record\\relate('Account', $accountId, 'opportunities', $opportunityId)`\n\n    `record\\relate('Account', $accountId, 'tasks', list('id1', 'id2'))`\n\n    ```\n    $columnData = object\\create();\n    $columnData['role'] = 'Tester';\n    record\\relate('Account', $accountId, 'contacts', $contactId, $columnData);\n    ```\n\n!!! note\n    This function won't work in *Before save script* when applied for the current record. Use an after-save Workflow rule instead.\n    \n## record\\unrelate\n\n`record\\unrelate(ENTITY_TYPE, ID, LINK, FOREIGN_ID)`\n\nUnlinks two records.\n\n!!! example\n\n    `record\\unrelate('Account', $accountId, 'opportunities', $opportunityId)`\n    \n!!! note\n\n    It won't work in *Before save script* when applied for the current record. Use an after-save Workflow rule instead.\n\n## record\\create\n\n`record\\create(ENTITY_TYPE, ATTRIBUTE1, VALUE1, [ATTRIBUTE2, VALUE2 ...])`\n\nor\n\n`record\\create(ENTITY_TYPE, OBJECT)` (as of v9.0)\n\nCreates a new record of entity type with attributes specified as key-value pairs or in an object. Returns the ID of the created record.\n\n!!! example\n\n    `$id = record\\create('Meeting', 'emailAddress', 'SOME@ADDRESS.com', 'assignedUserId', 'SOME-USER-ID')`\n\n## record\\update\n\n`record\\update(ENTITY_TYPE, ID, ATTRIBUTE1, VALUE1, [ATTRIBUTE2, VALUE2 ...])`\n\nor\n\n`record\\update(ENTITY_TYPE, ID, OBJECT)` (as of v9.0)\n\nUpdates an existing record with attributes specified as key-value pairs or an object.\n\n!!! example\n\n    `record\\update('Meeting', 'SOME-MEETING-ID', 'emailAddress', 'SOME@ADDRESS.com', 'assignedUserId', 'SOME-USER-ID')`\n\nIt will update the meeting with ID `SOME-MEETING-ID`, and will set `emailAddress = 'SOME@ADDRESS.com'`, `assignedUserId = 'SOME-USER-ID'`.\n\n## record\\delete\n\n`record\\delete(ENTITY_TYPE, ID)`\n\n*As of v7.4.*\n\nRemoves a record.\n\n## record\\relationColumn\n\n`record\\relationColumn(ENTITY_TYPE, ID, LINK, FOREIGN_ID, COLUMN)`\n\nReturns a relation column.\n\n!!! example\n\n    `record\\relationColumn('Account', $accountId, 'contacts', $contactId, 'role')`\n\n!!! example \"Example: Condition checking position in team\"\n\n    `record\\relationColumn('User', $someUserId, 'teams', 'some-team-id, 'role') == 'Support Manager'`\n\n## record\\updateRelationColumn\n\n`record\\updateRelationColumn(ENTITY_TYPE, ID, LINK, FOREIGN_ID, COLUMN, VALUE)`\n\nUpdates a relation column.\n\n!!! example\n\n    `record\\updateRelationColumn('Account', $accountId, 'contacts', $contactId, 'role', 'CEO')`\n"
  },
  {
    "path": "docs/administration/formula/string.md",
    "content": "# Formula > Functions > String\n\n* [string\\concatenate](#stringconcatenate)\n* [string\\substring](#stringsubstring)\n* [string\\contains](#stringcontains)\n* [string\\pos](#stringpos)\n* [string\\test](#stringtest)\n* [string\\length](#stringlength)\n* [string\\trim](#stringtrim)\n* [string\\lowerCase](#stringlowercase)\n* [string\\upperCase](#stringuppercase)\n* [string\\pad](#stringpad)\n* [string\\match](#stringmatch)\n* [string\\matchAll](#stringmatchall)\n* [string\\matchExtract](#stringmatchextract)\n* [string\\replace](#stringreplace)\n* [string\\split](#stringsplit)\n\n\n## string\\concatenate\n\n`string\\concatenate(STRING_1, STRING_2)`\n\nConcatenates two or more strings.\n\n!!! example\n\n    ```\n    $someVariable = string\\concatenate('ab', 'cd'); // will return 'abcd'\n    ```\n\n## string\\substring\n\n`string\\substring(STRING, START, LENGTH)`\n\nExtracts the characters from a STRING by START position and LENGTH.\n\nIf LENGTH is omitted, the substring starting from START until the end of the STRING will be returned.\n\nIf LENGTH is negative, then that many characters will be omitted from the end of STRING.\n\n!!! example\n\n    ```\n    $someVariable = string\\substring('abcde', 1, 2); // will return 'bc'\n\n    $someVariable = string\\substring('abcde', 1, -1); // will return 'bcd'\n    ```\n\n## string\\contains\n\n`string\\contains(STRING, NEEDLE)`\n\nWhether STRING contains NEEDLE.\n\n!!! example\n\n    ```\n    string\\contains('hello world', 'world') // will return true\n    ```\n\n## string\\pos\n\n`string\\pos(STRING, NEEDLE)`\n\nReturns position of NEEDLE in STRING, *false* if not found.\n\n!!! example\n\n    ```\n    string\\pos('hello world', 'world') // will return `6`\n    ```\n\n## string\\test\n\n`string\\test(STRING, REGULAR_EXPRESSION)`\n\nSearch a match between REGULAR_EXPRESSION and STRING. Returns TRUE of FALSE.\n\n!!! example\n\n    ```\n    string\\test('hello world', '/hello/i') // will return TRUE\n    ```\n\n## string\\length\n\n`string\\length(STRING)`\n\nThe length of STRING.\n\n!!! example\n\n    ```\n    string\\length('hello world') // will return `11`\n    ```\n\n## string\\trim\n\n`string\\trim(STRING)`\n\nStrips whitespace from the beginning and end of STRING.\n\n!!! example\n\n    ```\n    string\\trim(' hello world ') // will return `hello world`\n    ```\n\n## string\\lowerCase\n\n`string\\lowerCase(STRING)`\n\nConverts letters to lower case.\n\n!!! example\n\n    ```\n    string\\lowerCase('HELLO world') // will return `hello world`\n    ```\n\n## string\\upperCase\n\n`string\\upperCase(STRING)`\n\nConverts letters to upper case.\n\n!!! example\n\n    ```\n    string\\upperCase('HELLO world') // will return `HELLO WORLD`\n    ```\n\n## string\\pad\n\n`string\\pad(STRING, LENGTH, [PAD_STRING], [PAD_TYPE])`\n\nPads STRING to a certain LENGTH with PAD_STRING.\n\nPAD_STRING by default is a whitespace string `' '`.\n\nPAD_TYPE can be *'right'*, *'left'*, *'both'*. By default it is *'right'*.\n\n!!! example\n\n    ```\n    string\\pad('100', 5, '*', 'right') // will return `100**`\n    ```\n\n## string\\match\n\n`string\\match(STRING, REGULAR_EXPRESSION, [OFFSET])`\n\nRetrieves the first result of matching a STRING against a REGULAR_EXPRESSION. Returns NULL if no matches are found.\n\n!!! example\n\n    ```\n    string\\match('{token1} foo {token2} bar', '/{[^}]*}/')\n    ```\n\n    Will return `{token1}`.\n\nThe slash character `/` defines the start and the end of a REGULAR_EXPRESSION.\n\n## string\\matchAll\n\n`string\\matchAll(STRING, REGULAR_EXPRESSION, [OFFSET])`\n\nRetrieves all results of matching a STRING against a REGULAR_EXPRESSION. Returns NULL if no matches are found.\n\n!!! example\n\n    ```\n    string\\matchAll('{token1} foo {token2} bar', '/{[^}]*}/')\n    ```\n\n    Will return an array `['{token1}', '{token2}']`.\n    \n## string\\matchExtract\n\n`string\\matchExtract(STRING, REGULAR_EXPRESSION)`\n\n*As of v7.4.*\n\nReturns an array of substrings that match parenthesized sub-patterns. Returns NULL if no matches are found.\n\n!!! example\n\n    ```\n    string\\matchExtract('values: 1000 2000', '/values\\: (.*) (.*)$/')\n    ```\n\n    Will return `['1000', '2000']`.\n\nThe slash character `/` defines the start and the end of a REGULAR_EXPRESSION.\n\n## string\\replace\n\n`string\\replace(STRING, SEARCH, REPLACE)`\n\nReplaces all occurrences of SEARCH with REPLACE in STRING.\n\n!!! example\n\n    ```\n    string\\replace('Hello {test}', '{test}', 'world')\n    ```\n\n    Will return `'Hello world'`.\n\n!!! note\n\n    The REPLACE parameter must be a string. Use [number\\format](number.md#numberformat) function to cast an integer or a float to a string.\n\n\n## string\\split\n\n`string\\split(STRING, SEPARATOR)`\n\nSplits a STRING into array of strings by a string SEPARATOR. (as of v7.1)\n\n!!! example\n\n    ```\n    string\\split('hello world', ' ') // will return ['hello', 'world']\n    ```\n"
  },
  {
    "path": "docs/administration/formula/util.md",
    "content": "# Formula > Functions > Util\n\n* [util\\generateId](#utilgenerateid)\n* [util\\generateRecordId](#utilgeneraterecordid)\n* [util\\base64Encode](#utilbase64encode)\n* [util\\base64Decode](#utilbase64decode)\n\n## util\\generateId\n\nGenerates a unique ID. Returns a string.\n\n!!! example\n\n    ```\n    $uniqueId = util\\generateId();\n    ```\n\n## util\\generateRecordId\n\n*As of v7.5.*\n\nGenerates an ID that can be used as an ID for an entity. Returns a string.\n\n!!! example\n\n    ```\n    $recordId = util\\generateRecordId();\n    ```\n\n## util\\base64Encode\n\n*As of v8.3.*\n\nBase64 encode.\n\n## util\\base64Decode\n\n*As of v8.3.*\n\nBase64 decode.\n"
  },
  {
    "path": "docs/administration/formula-functions.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Formula Functions\n\nThe format of function usage: `groupName\\functionName(argument1, argument2, ..., argumentN)`.\n\nOut-of-the-box functions are listed below.\n\nFunctions:\n\n* [General](#general)\n* [String](#string)\n* [Datetime](#datetime)\n* [Number](#number)\n* [Entity](#entity)\n* [Record](#record)\n* [Env](#env)\n* [Password](#password)\n* [Array](#array)\n* [Object](#object)\n* [Language](#language)\n* [Json](#json)\n* [Ext](#ext)\n* [Util](#util)\n* [Log](#log)\n* [Exception](#exception)\n\n## General\n\n[general](formula/general.md)\n\n* [list](formula/general.md#list)\n* [ifThenElse](formula/general.md#ifthenelse)\n* [ifThen](formula/general.md#ifthen)\n\n## String\n\n[string](formula/string.md)\n\n* [string\\concatenate](formula/string.md#stringconcatenate)\n* [string\\substring](formula/string.md#stringsubstring)\n* [string\\contains](formula/string.md#stringcontains)\n* [string\\pos](formula/string.md#stringpos)\n* [string\\test](formula/string.md#stringtest)\n* [string\\length](formula/string.md#stringlength)\n* [string\\trim](formula/string.md#stringtrim)\n* [string\\lowerCase](formula/string.md#stringlowercase)\n* [string\\upperCase](formula/string.md#stringuppercase)\n* [string\\pad](formula/string.md#stringpad)\n* [string\\match](formula/string.md#stringmatch)\n* [string\\matchAll](formula/string.md#stringmatchall)\n* [string\\matchExtract](formula/string.md#stringmatchextract)\n* [string\\replace](formula/string.md#stringreplace)\n* [string\\split](formula/string.md#stringsplit)\n\n## Datetime\n\n[datetime](formula/datetime.md)\n\n* [datetime\\today](formula/datetime.md#datetimetoday)\n* [datetime\\now](formula/datetime.md#datetimenow)\n* [datetime\\format](formula/datetime.md#datetimeformat)\n* [datetime\\date](formula/datetime.md#datetimedate)\n* [datetime\\month](formula/datetime.md#datetimemonth)\n* [datetime\\year](formula/datetime.md#datetimeyear)\n* [datetime\\hour](formula/datetime.md#datetimehour)\n* [datetime\\minute](formula/datetime.md#datetimeminute)\n* [datetime\\dayOfWeek](formula/datetime.md#datetimedayofweek)\n* [datetime\\diff](formula/datetime.md#datetimediff)\n* [datetime\\addSeconds](formula/datetime.md#datetimeaddseconds)\n* [datetime\\addMinutes](formula/datetime.md#datetimeaddminutes)\n* [datetime\\addHours](formula/datetime.md#datetimeaddhours)\n* [datetime\\addDays](formula/datetime.md#datetimeadddays)\n* [datetime\\addWeeks](formula/datetime.md#datetimeaddweeks)\n* [datetime\\addMonths](formula/datetime.md#datetimeaddmonths)\n* [datetime\\addYears](formula/datetime.md#datetimeaddyears)\n* [datetime\\closest](formula/datetime.md#datetimeclosest)\n\n## Number\n\n[number](formula/number.md)\n\n* [number\\format](formula/number.md#numberformat)\n* [number\\abs](formula/number.md#numberabs)\n* [number\\power](formula/number.md#numberpower)\n* [number\\round](formula/number.md#numberround)\n* [number\\floor](formula/number.md#numberfloor)\n* [number\\ceil](formula/number.md#numberceil)\n* [number\\randomInt](formula/number.md#numberrandomint)\n* [number\\parseInt](formula/number.md#numberparseint)\n* [number\\parseFloat](formula/number.md#numberparsefloat)\n\n## Entity\n\n[entity](formula/entity.md)\n\n* [entity\\isNew](formula/entity.md#entityisnew)\n* [entity\\isAttributeChanged](formula/entity.md#entityisattributechanged)\n* [entity\\isAttributeNotChanged](formula/entity.md#entityisattributenotchanged)\n* [entity\\attribute](formula/entity.md#entityattribute)\n* [entity\\setAttribute](formula/entity.md#entitysetattribute)\n* [entity\\clearAttribute](formula/entity.md#entityclearattribute)\n* [entity\\attributeFetched](formula/entity.md#entityattributefetched)\n* [entity\\addLinkMultipleId](formula/entity.md#entityaddlinkmultipleid)\n* [entity\\hasLinkMultipleId](formula/entity.md#entityhaslinkmultipleid)\n* [entity\\removeLinkMultipleId](formula/entity.md#entityremovelinkmultipleid)\n* [entity\\setLinkMultipleColumn](formula/entity.md#entitysetlinkmultiplecolumn)\n* [entity\\isRelated](formula/entity.md#entityisrelated)\n* [entity\\sumRelated](formula/entity.md#entitysumrelated)\n* [entity\\countRelated](formula/entity.md#entitycountrelated)\n* [entity\\getLinkColumn](formula/entity.md#entitygetlinkcolumn)\n\n## Record\n\n[record](formula/record.md)\n\n* [record\\exists](formula/record.md#recordexists)\n* [record\\count](formula/record.md#recordcount)\n* [record\\findOne](formula/record.md#recordfindone)\n* [record\\findMany](formula/record.md#recordfindmany)\n* [record\\findRelatedOne](formula/record.md#recordfindrelatedone)\n* [record\\findRelatedMany](formula/record.md#recordfindrelatedmany)\n* [record\\attribute](formula/record.md#recordattribute)\n* [record\\fetch](formula/record.md#recordfetch)\n* [record\\relate](formula/record.md#recordrelate)\n* [record\\unrelate](formula/record.md#recordunrelate)\n* [record\\create](formula/record.md#recordcreate)\n* [record\\update](formula/record.md#recordupdate)\n* [record\\delete](formula/record.md#recorddelete)\n* [record\\relationColumn](formula/record.md#recordrelationcolumn)\n* [record\\updateRelationColumn](formula/record.md#recordupdaterelationcolumn)\n\n## Env\n\n[env](formula/env.md)\n\n* [env\\userAttribute](formula/env.md#envuserattribute)\n\n## Password\n\n[password](formula/password.md)\n\n* [password\\generate](formula/password.md#passwordgenerate)\n* [password\\hash](formula/password.md#passwordhash)\n\n## Array\n\n[array](formula/array.md)\n\n* [array\\includes](formula/array.md#arrayincludes)\n* [array\\push](formula/array.md#arraypush)\n* [array\\length](formula/array.md#arraylength)\n* [array\\at](formula/array.md#arrayat)\n* [array\\join](formula/array.md#arrayjoin)\n* [array\\indexOf](formula/array.md#arrayindexof)\n* [array\\removeAt](formula/array.md#arrayremoveat)\n* [array\\unique](formula/array.md#arrayunique)\n\n## Object\n\n[object](formula/object.md)\n\n* [object\\create](formula/object.md#objectcreate)\n* [object\\get](formula/object.md#objectget)\n* [object\\set](formula/object.md#objectset)\n* [object\\clear](formula/object.md#objectclear)\n* [object\\has](formula/object.md#objecthas)\n* [object\\cloneDeep](formula/object.md#objectclonedeep)\n\n## Language\n\n[language](formula/language.md)\n\n* [language\\translate](formula/language.md#languagetranslate)\n* [language\\translateOption](formula/language.md#languagetranslateoption)\n\n## Json\n\n[json](formula/json.md)\n\n* [json\\retrieve](formula/json.md#jsonretrieve)\n* [json\\encode](formula/json.md#jsonencode)\n\n## Ext\n\n[ext](formula/ext.md)\n\n* [ext\\account\\findByEmailAddress](formula/ext.md#extaccountfindbyemailaddress)\n* [ext\\currency\\convert](formula/ext.md#extcurrencyconvert)\n* [ext\\email\\send](formula/ext.md#extemailsend)\n* [ext\\email\\applyTemplate](formula/ext.md#extemailapplytemplate)\n* [ext\\markdown\\transform](formula/ext.md#extmarkdowntransform)\n* [ext\\sms\\send](formula/ext.md#extsmssend)\n* [ext\\pdf\\generate](formula/ext.md#extpdfgenerate)\n* [ext\\user\\sendAccessInfo](formula/ext.md#extusersendaccessinfo)\n* [ext\\calendar\\userIsBusy](formula/ext.md#extcalendaruserisbusy)\n* [ext\\acl\\checkEntity](formula/ext.md#extaclcheckentity)\n* [ext\\acl\\checkScope](formula/ext.md#extaclcheckscope)\n* [ext\\acl\\getLevel](formula/ext.md#extaclgetlevel)\n* [ext\\acl\\getPermissionLevel](formula/ext.md#extaclgetpermissionlevel)\n* [ext\\oauth\\getAccessToken](formula/ext.md#extoauthgetaccesstoken)\n* [ext\\appSecret\\get](formula/ext.md#extappsecretget)\n\n## Util\n\n[util](formula/util.md)\n\n* [util\\generateId](formula/util.md#utilgenerateid)\n* [util\\generateRecordId](formula/util.md#utilgeneraterecordid)\n* [util\\base64Encode](formula/util.md#utilbase64encode)\n* [util\\base64Decode](formula/util.md#utilbase64decode)\n\n## Log\n\n[log](formula/log.md)\n\n* [log\\info](formula/log.md#loginfo)\n* [log\\notice](formula/log.md#lognotice)\n* [log\\warning](formula/log.md#logwarning)\n* [log\\error](formula/log.md#logerror)\n\n## Exception\n\n[exception](formula/exception.md)\n\n* [exception\\throwInvalid](formula/exception.md#exceptionthrowinvalid)"
  },
  {
    "path": "docs/administration/formula-scripts-examples.md",
    "content": "# Formula Scripts Examples\n\n* [Creating new user](#creating-new-user)\n* [Sending email with generated PDF in attachment](#sending-email-with-generated-pdf-in-attachment)\n\n\n## Creating new user\n\n```\n// assuming we have $userName and $emailAddress variables defined above\n\n$password = password\\generate();\n$hash = password\\hash($password);\n\n$userId = record\\create('User',\n    'userName', $userName,\n    'password', $hash,\n    'emailAddress', $emailAddress\n);\n\n$emailBody = string\\concatenate(\n    'Username: ', $userName, '\\n',\n    'Password: ', $password, '\\n'\n);\n\n$emailId = record\\create(\n    'Email',\n    'to', $emailAddress,\n    'status', 'Sending',\n    'subject', 'Access info',\n    'body', $emailBody,\n    'isHtml', false\n);\n\next\\email\\send($emailId);\n```\n\n## Sending email with generated PDF in attachment\n\n```\n$attachmentId = ext\\pdf\\generate(\n    'Quote', entity\\attribute('id'), 'copy-pdf-template-id-here', 'test.pdf'\n);\n\n$emailId = record\\create('Email',\n    'to', entity\\attribute('emailAddress'),\n    'attachmentsIds', list($attachmentId)\n);\n\n// applying email template\next\\email\\applyTemplate($emailId, 'copy-email-template-id-here');\n\next\\email\\send($emailId);\n```\n"
  },
  {
    "path": "docs/administration/formula.md",
    "content": "---\nsearch:\n  boost: 3\n---\n\n# Formula Script\n\nFormula Script is a simple scripting language designed specially for EspoCRM. It's a tool that provides the ability to manipulate data and automatically perform operations.\n\nWhere it can be used:\n\n* [Before-save script](entity-manager.md#before-save-custom-script)\n* [API before-save script](api-before-save-script.md)\n* [Workflows](workflows.md) tool (in conditions and actions)\n* [BPM](bpm.md) tool\n* [Formula sandbox](#sandbox)\n\nFormula scripts are meant to be written directly within the Espo application UI, with no need for environment configuration or building steps. Even users with little or no programming experience can experiment with writing simple scripts, allowing them to fine-tune their system to better suit their needs.\n\nIn this article:\n\n* [Syntax](#syntax)\n* [Operators](#operators)\n* [Control structures](#control-structures)\n* [Attributes](#attributes)\n* [Functions](#functions)\n* [Values](#values)\n* [Variables](#variables)\n* [Comments](#comments)\n* [Comparison](#comparison)\n* [Examples](#examples)\n* [Explanation](#explanation)\n* [Function arguments](#function-arguments)\n* [Sandbox](#sandbox)\n* [See also](#see-also)\n\n## Syntax\n\nThere are 6 language elements in Formula script:\n\n* operators (e.g. `+`, `-`, `*`)\n* control structures (`if`, `while`)\n* functions (e.g. `string\\concatenate()`)\n* values (scalars and NULL value, e.g. `'string'`, `100`, `true`, `null`)\n* variables (e.g. `$temp`)\n* attributes (values of the current entity, e.g. `contactId`, `status`)\n\nSeparate expressions must be delimited by a semicolon character `;`.\n\n!!! example\n\n    ```\n    string\\concatenate(name, ' + ', $test);\n    ```\n    where:\n\n    * `string\\concatenate` – a function\n    * `name` – an attribute (of a target entity, to which formula is applied)\n    * `' + '` – a value (of string type)\n    * `$test` – a variable (supposed to be declared somewhere above)\n\nAvailable scalar types:\n\n* string – `'string'`\n* int – `1000`\n* float – `1000.5`\n* boolean – `true` or `false`\n\n### Implicit return\n\n*As of v9.1.*\n\nThe last evaluated expression is returned.\n\nExample:\n\n```\n$a = 1;\n$b = $a + 1;\n$b;\n```\n\nThis script is treated as an expression and the value of the variable $b is returned. Can be useful when Formula is used to evaluate a condition or determine a value.\n\n## Operators\n\n* `=` – assignment,\n* `??` – null coalescing (as of v7.1),\n* `||` – logical OR,\n* `&&` – logical AND,\n* `!` – logical NOT,\n* `+` – numeric summation,\n* `-` – numeric subtraction,\n* `*` – numeric multiplication,\n* `/` – numeric division,\n* `%` – numeric modulo,\n* `==` – comparison equals,\n* `!=` – comparison not equals,\n* `>` – comparison greater than,\n* `<` – comparison less than,\n* `>=` – comparison greater than or equals,\n* `<=` – comparison less than or equals.\n\nThe priority of operators:\n\n* `=`;\n* `??`;\n* `||`;\n* `&&`\n* `==`, `!=`, `>`, `<`, `>=`, `<=`;\n* `+`, `-`;\n* `*`, `/`, `%`.\n\n## Control structures\n\n### if\n\n*As of v7.4.*\n\n```\nif (CONDITION) {\n    CODE\n}\n\nif (CONDITION) {\n    CODE\n} else {\n    CODE\n}\n\nif (CONDITION) {\n    CODE\n} else if (CONDITION) {\n    CODE\n} else {\n    CODE\n}\n```\n\n### while\n\n*As of v7.4.*\n\n```\nwhile (CONDITION) {\n    CODE\n}\n\nwhile (CONDITION1) {\n    if (CONDITION2) {\n        break;\n    }\n\n    if (CONDITION3) {\n        continue;\n    }\n}\n```\n\n## Attributes\n\n[Attributes](terms-and-naming.md#attribute) represent field values of a target entity. You can insert available attributes by clicking the plus button.\n\nIt's possible to access attributes of related entities with the following expression `linkName.attributeName`.\n\nThe attribute element type was introduced in the language to be able to write like this:\n\n```\n// Setting an attribute.\ndescription = 'test';\n\n// Getting an attribute.\n$variable = description;\n```\n\nIf we didn't have attributes, we would need to write more verbose:\n\n```\nentity\\setAttribute('description', 'test');\n$variable = entity\\getAttribute('description');\n```\n\n## Functions\n\nFormat of function usage:\n\n```\ngroupName\\functionName(argument1, argument2, ..., argumentN)\n```\n\nSee the full list of [built-in functions](formula-functions.md).\n\nDevelopers can also create [custom functions](../development/new-function-in-formula.md).\n\n## Values\n\n* Strings. E.g. `'some string'`, `\"some string\"`.\n* Integer numbers. E.g. `1`, `100`, `40300`.\n* Float numbers. E.g. `5.2`.\n* Booleans: `true`, `false`.\n* Null: `null`.\n\n## Variables\n\nVariables starts with a dollar sign.\n\n```\n// Assign the value to the variable.\n$someVariableName = 'Test';\n\n// Assign the variable to the attribute (field).\ndescription = $test;\n```\n\n### Array appending\n\n*As of v9.1.*\n\nIf a variable is an array, it's possible to append a value to it with the following syntax:\n\n```\n$list[] = 'value';\n```\n\n### Incrementing and decrementing\n\n*As of v9.1.*\n\nIncrementing an integer variable:\n\n```\n$a++;\n```\n\nDecrementing an integer variable:\n\n```\n$a--;\n```\n\n### Accessing by key\n\n*As of v9.1.*\n\nArrays:\n\n```\n$list = list();\n\n$list[0] = '0';\n$list[1] = '1';\n$list[0 + 2] = '2';\n\n$v = $list[2];\n```\n\nObjects:\n\n```\n$o = object\\create();\n\n$o['a'] = 'a';\n\n$v = $o['a'];\n```\n\nReading by a non-existent key results in an error.\n\nNull-coalescing prevents the error:\n\n```\n$list = list();\n\n$v = $list[0] ?? 0;\n```\n\n## Comments\n\nLine comment:\n\n```\n// comment\n```\n\nSection comment:\n\n```\n/*\n    comment\n*/\n```\n\n## Comparison\n\nThe following comparison operators are available:\n\n* `==` – equals,\n* `!=` – not equals,\n* `>` – greater than,\n* `<` – less than,\n* `>=` – greater than or equals,\n* `<=` – less than or equals.\n\n!!! important\n\n    A strict comparison is used. If you compare an int `1` to a float `1.0` with `==` operator, they are treated as not equal. You need to compare values of same types or check whether a value falls within a range with `$a - 0.0001 <= $b && $b <= $a + 0.0001`.\n\n\n## Examples\n\n!!! example\n\n    ```\n    if (entity\\isNew()) {\n        assignedUserId = null;\n        status = 'Assigned';\n    }\n    \n    someDateField = ifThen(\n        entity\\isNew() && closeDate == null && stage == 'Closed Won',\n        datetime\\today()\n    );\n    ```\n\n!!! example\n\n    ```\n    amount = product.listPrice - (product.listPriceConverted * discount / 100.0);\n    amountCurrency = 'USD';\n    ```\n\n!!! example\n\n    ```\n    someField = string\\concatenate(firstName, \" '\", middleName, \"' \", lastName);\n    ```\n\n!!! example\n\n    ```\n    if (entity\\isNew() && status == 'Planned' && dateStart == null) {\n        dateStart = datetime\\addDays(datetime\\now(), 10);\n    } else if (status == 'Held' && dateStart == null) {\n        dateStart = datetime\\now();\n    }\n    ```\n\n## Explanation\n\nFunctions accept expressions as arguments. \n\n```\nsomeFunction(EXPRESSION1, EXPRESSION2);\n```\n\nExpressions can be:\n\n* scalar value\n* variable\n* attribute\n* combination of all those forming an expression\n\nScalar STRING as an argument:\n\n```\nsomeFunction('some string');\n```\n\nScalar INT as an argument:\n\n```\nsomeFunction(10);\n```\n\nScalar FLOAT as an argument:\n\n```\nsomeFunction(10.5);\n```\n\nScalar BOOLEAN as an argument:\n\n```\nsomeFunction(true);\n```\n\nNULL value as an argument:\n\n```\nsomeFunction(null);\n```\n\nExpression as an argument:\n\n```\nsomeFunction(2 + 2);\n```\n\nExpression as an argument:\n\n```\nsomeFunction(anotherFunction());\n```\n\nVariable as an argument:\n\n```\nsomeFunction($someVariable);\n```\n\nAttribute as an argument:\n\n```\nsomeFunction(attributeName);\n```\n\n## Function arguments\n\nBelow are explanations of function arguments which are met in the documentation.\n\n#### LINK\n\nA name of the relationship. Available link names can be found at Administration > Entity Manager > {Entity Type} > Relationships. More info about links [here](terms-and-naming.md#link).\n\nLink names must be wrapped in quotes when used as function arguments. Example: `record\\relate('Contact', 'someContactId', 'opportunities', 'someContactId')`.\n\n#### ATTRIBUTE\n\nAttribute name usually is the same as a system field name. Fields are listed at Administration > Entity Manager > {Entity Type} > Fields. More info about attributes [here](terms-and-naming.md#attribute).\n\nField types having multiple attributes:\n\n* Link: *fieldId*, *fieldName*.\n* Link-Multiple: *fieldIds*, *fieldNames*.\n* Link-Parent: *fieldId*, *fieldType*, *fieldName*.\n* Currency: *field*, *fieldCurrency*.\n\nWhere *field* is the name of the field.\n\nAttribute names must be wrapped in quotes when used as function arguments. Example: `record\\attribute('Lead', 'someId', 'assignedUserId')`.\n\n#### ENTITY_TYPE\n\nThe list of entity types is available at Administration > Entity Manager. More info about entity types [here](terms-and-naming.md#entity-type).\n\nEntity type names must be wrapped in quotes when used as function arguments. Example: `record\\attribute('Lead', 'someId', 'assignedUserId')`.\n\n#### FILTER\n\nCan be:\n\n* primary filter name (as string)\n* where item (as object; as of v9.2)\n\n##### Primary filter\n\nA name of a filter pre-defined in the system. Developers can define own [filters](../development/metadata/select-defs.md#primaryfilterclassnamemap).\n\nFor non-developers, it's possible to apply a [List Report](../user-guide/reports.md#list-reports) as a filter. First, you need to create a [Report Filter](../user-guide/reports.md#report-filters) (at Administration page). Then, you can use the filter name `reportFilter{filterId}` in functions `record\\count`, `record\\findOne`, `record\\findRelatedOne`, `record\\findRelatedMany`, `entity\\sumRelated`, `entity\\countRelated`.\n\n!!! example\n\n    `entity\\sumRelated('opportunities', 'amountConverted', 'reportFilter5c41a0a396f66725d')`\n    \n    Where *5c41a0a396f66725d* is an ID of the Report Filter record which you can obtain from the URL.\n\n##### Where item\n\n*As of v9.2.*\n\nThe syntax is the same as for the *where* [parameter](../development/api-search-params.md#where-items) in API requests.\n\n!!! example\n\n    ```\n    $where = object\\create();\n    $where['type'] = 'or';\n    $where['value'] = list(\n        (\n            $it = object\\create();\n            $it['type'] = 'equals';\n            $it['attribute'] = 'type';\n            $it['value'] = 'Customer';\n            $it;\n        ),\n        (\n            $it = object\\create();\n            $it['type'] = 'equals';\n            $it['attribute'] = 'type';\n            $it['value'] = 'Partner';\n            $it;\n        )\n    );        \n    \n    $output = record\\findMany('Account', 10, null, null, $where);\n    ```\n\n## Sandbox\n\nThe Formula Sandbox provides the ability to test and debug formula scripts. Available under Administration > Formula Sandbox. \n\nUse the function `output\\printLine` to print values for debugging purposes. \n\nYou can also utilize the sandbox to run one-time scripts, for example, to modify some data in your system.\n\n## See also\n\n* [Formula functions](formula-functions.md)\n* [Formula scripts examples](formula-scripts-examples.md)\n* [Formula quick tour](https://app.supademo.com/demo/cmljmuit94td75351htrpagg2)\n* [Custom functions](../development/new-function-in-formula.md)\n"
  },
  {
    "path": "docs/administration/iis-server-configuration.md",
    "content": "# IIS server configuration for EspoCRM\n\n*As of v7.0.*\n\nThese instructions are supplementary to the [server configuration](server-configuration.md) guidelines. All configuration settings listed here are made on Windows Server 2019.\n\n!!! note\n\n    [URL Rewrite](https://www.iis.net/downloads/microsoft/url-rewrite) must be installed on the IIS server.\n\nTo сonfigure IIS server for EspoCRM, do the following steps.\n\n## Step 1. Physical Path adjusting\n\n1.1. Go to **IIS Manager**, select your *Site*.\n\n![IIS Manager](../_static/images/administration/iis/iis-manager.png)\n\n1.2. Right-click on *Site* > *Manage Website* > *Advanced Settings*.\n\n![Physical Path](../_static/images/administration/iis/physical-path.png)\n\n1.3. Specify your EspoCRM public directory path (e.g. `C:\\inetpub\\wwwroot\\EspoCRM-7.2.7\\public`) in the *Physical Path* field.\n\n1.4. Click on *OK*.\n\n![Physical Path-2](../_static/images/administration/iis/physical-path-2.png)\n\n## Step 2. Virtual Path adjusting\n\n2.1. Right-click on *Site* in **IIS manager** > *Add Virtual Directory*.\n\n![Virtual Path](../_static/images/administration/iis/virtual-path.png)\n\n2.3. Type the *client* name in the *Alias* field.\n\n2.4. Specify your EspoCRM client directory path (e.g. `C:\\inetpub\\wwwroot\\EspoCRM-7.2.7\\client`) in the *Physical Path* field.\n\n2.5. Click on *OK*.\n\n![Virtual Path-2](../_static/images/administration/iis/virtual-path-2.png)\n\n## Step 3. Handler Mappings settings\n\n### Via IIS Manager\n\n3.1. Navigate the **Handler Mappings** scope of your *Site*.\n\n![Handler Mappings](../_static/images/administration/iis/handler-mappings.png)\n\n3.2. Select the *PHP_via_FastCGI* module > *Actions* > *Edit*.\n\n![FastCGI](../_static/images/administration/iis/fast-cgi.png)\n\n3.3. Specify `\"C:\\Program Files\\PHP\\v7.4\\php-cgi.exe\"` path in the *Executable (Optional)* field (double quotes are required).\n\n![Edit Module](../_static/images/administration/iis/edit-module.png)\n\n3.4. Navigate *Request Restrictions* > *Verbs*.\n\n3.5. Specify the verbs to be handled. Select *All verbs* or specify *One of the following verbs:* `GET,HEAD,POST,PUT,DELETE,PATCH`, click on *OK*.\n\n![Verbs](../_static/images/administration/iis/verbs.png)\n\n3.6. Click on *OK* and *Yes*.\n\n![Confirmation](../_static/images/administration/iis/confirmation.png)\n\n### Via Text Editor (Notepad as Administrator, Sublime Text, VSCode, etc.)\n\n3.1. Open `%windir%\\system32\\inetsrv\\config\\applicationhost.config` file.\n\n3.2. Locate the *< handlers >* tag.\n\n3.3. Locate the *\"PHP_via_FastCGI\"* section, add all HTTP methods modifying `verb=\"GET,HEAD,POST\"` value to `verb=\"GET,HEAD,POST,PUT,DELETE,PATCH\"`.\n\n3.4. Save the *ApplicationHost.config* file.\n\n## Step 4. Permissions\n\n4.1. Open your EspoCRM instance directory, right-click on it > *Properties* > *Security* > *Edit*.\n\n4.2. For user names **IIS_IUSRS**, check all available boxes in the *Allow* column.\n\n![Permissions](../_static/images/administration/iis/permissions.png)\n\n4.3. Click on *Apply* and *OK*.\n\n**Reboot your IIS server after all the steps are done.**\n"
  },
  {
    "path": "docs/administration/import.md",
    "content": "# Import\n\nProvides the ability to import records from CSV files.\n\nAn administrator can access the Import tool at Administration > Import. By default, regular users don't have access to Import but it can be granted in Roles. The administrator can also add the *Import* tab to the navbar at Administration > User Interface > Tab List.\n\nIn this article:\n\n* [Step 1](#step-1)\n* [Step 2](#step-2)\n* [Import results](#import-results)\n* [Importing into Target List](#importing-into-target-list)\n* [Relations](#relations)\n* [Console commands](#console-commands)\n* [Errors](#errors)\n* [See also](#see-also)\n\n## Step 1\n\nSelect what type of records you need to import (*Entity Type* field).\nSelect a CSV file. A file should be formatted in *UTF-8*.\nSelect *What to do?*. Available options: Create Only, Create & Update, Update Only.\n\n* *Create Only* − import will only create records;\n* *Create & Update* − records will be created, if records with matching field values are found, they will be updated; you will be able to check what fields to match by on the _Step 2_.\n* *Update Only* − records with matching field values will be updated.\n\nOnce you select a CSV file, you will be able to see how it will be parsed in the **Preview** panel. When you change parameters, the preview is updated.\n\nParameters:\n\n* *Header Row* − whether a CSV file has the first row with field names.\n* *Execute in idle* − is recommended if you import a **big number of records**; import will be processed **via cron**; the status will be set to *Complete* when the import process is finished.\n* *Skip searching for duplicates* − will **make the import faster**.\n* *Silent mode* − the majority of after-save scripts will be skipped; Stream notes won't be created, workflows will be skipped; checking will **make the import faster**.\n* *Run Manually* − you will need to start the import manually from CLI. The command will be shown after setting up the import.\n* *Telephone country code* − phone numbers in a regional format will be converted to the international format according the selected country. (as of v8.1)\n\nClick the **Next** button to proceed to the _Step 2_.\n\n![1](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/import/step-1.png)\n\n## Step 2\n\nSet up the field mapping – how fields correspond to columns in the CSV file. Not mapped columns will be ignored.\n\nIf the import mode is *Create & Update* or *Update Only*, you also need to check the fields that will be used to find the records to update. For example, if you tick *update by* the Name field, then records where the Name matches the value in the CSV file will be updated.\n\nAdd **Default Values** that you want new and updated records to set with. For example, you can specify values for the Assigned User and Teams fields to be applied by default.\n\nAfter import is done, you will have the ability to **revert** created records. You will be able to see which records were recognized as duplicates and which were updated. Duplicate means that there was a similar record in the system. You can remove all imported duplicates at once or remove only specific ones.\n\n!!! important\n\n    Revert doesn't work with updated records, you cannot revert the update.\n\nClick the **Run Import** button to proceed. It may take some time before the import process gets finished. If you want to import a large bunch of records, it's recommended to run import *in idle*.\n\n![2](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/import/step-2.png)\n\n## Import results\n\n#### Remove import log\n\nOnce the records are imported and you are sure that imported data is fine, you can *Remove Import Log* (by clicking the button on the import results view) to preclude accidental reverting of the import.\n\n#### Revert import\n\n*Revert Import* will remove all imported records permanently.\n\n!!! important\n\n    Updates caused by import are not reverted.\n\n#### Remove duplicates\n\nThis will permanently remove all imported records that were recognized as duplicates.\n\n#### New import with same params\n\nThis will create a new import with the same parameters and field mapping.\n\n## Importing into Target List\n\nWhen you import Contacts, Leads or Accounts, you can add them to a specific Target List. On the Step 2, you need to add the *Target List* field in the *Default Values* panel and select a needed Target List record. You can also use *Update only* or *Create & Update* import type to link existing records with a specific Target List.\n\n## Relations\n\nIt's possible to automatically relate imported records by a foreign name. For example, when you import Opportunities, if you have Account names in a CSV but don't have Account IDs, Accounts with corresponding names will be automatically related with imported records. Note that this functionality is only available for many-to-one relationships.\n\nIt's also possible to automatically relate imported records by a *Foreign* field other than the Name. The Foreign field should have *Relate on Import* parameter enabled. The feature is available as of v8.2.\n\n## Console commands\n\nRun import:\n\n```\nphp command.php import --id={import-id}\n```\n\nThe import must be created via the UI before. It should have *Run Manually* parameter checked.\n\nResume failed import (from the last processed row):\n\n```\nphp command.php import --id={import-id} --resume\n```\n\nRevert import:\n\n```\nphp command.php import --id={import-id} --revert\n```\n\nImport file:\n\n```\nphp command.php import --file=path/to/csv --params-id={import-id}\n```\n\n*--params-id* is ID of a previously run import. Its parameters will be used for the import.\n\n## Errors\n\n*As of v7.2.*\n\nAll rows that failed to import will be available in the Errors panel on the Import result view. It's possible to view the reason of the failure (usually it's validation), the index of the failed row and values. To view error details, click the *View* action from the dropdown.\n\nThere's the ability to export all failed rows back to a CSV (in order to fix them and then re-import).\n\n### Integrity-Constraint-Violation\n\nOccurs when importing an ID that already exists. Most likely, you didn't reverted the previously imported records and try to import them again.\n\n### Validation\n\nValidation is applied for imported records. If a row does not pass validation, the record won't be created.\n\n#### Enum fields\n\nWhen importing to an enum field, values in a CSV should be the same as values (options) defined for the field in Espo. If your data source uses different values, consider replacing them in the CSV before importing. One can utilize the *VLOOKUP* function in the spreadsheet app or use simple *Find & Replace*.\n\nIf you import an empty value, but your enum field does not have an empty option, the validation will not pass.\n\n## See also\n\n* [Import feature quick tour](https://app.supademo.com/demo/cmh1o4qs909i5nitlciznubzc)\n* [Export Import extension](../extensions/export-import/overview.md)\n* [Import and export tool for quick data migration](https://www.espocrm.com/tips/import-export/)\n"
  },
  {
    "path": "docs/administration/installation-by-script.md",
    "content": "# Installation by Script\n\nThis script automatically installs EspoCRM as a Docker image with Nginx server and MariaDB database.\n\n## Requirements\n\n1. Operating system:\n\n  * Ubuntu\n  * Debian\n  * Linux Mint\n\n2. Access via command line.\n\n3. Root or sudo access.\n\n## Installation\n\nOpen your server's command line and run the commands:\n\n```\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh\n```\n\n## Installation with SSL/TLS certificate\n\n```\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh --ssl\n```\n\n## Installation without prompts\n\n```\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh -y --ssl --letsencrypt --domain=my-espocrm.com --email=email@my-domain.com\n```\n\n## Available options\n\n#### `-y` or `--yes`\n\nSkip confirmation prompts during installation.\n\n#### `--ssl`\n\nInstallation with SSL/TLS certificate. Ex. `--ssl`. See [installation modes](#installation-modes).\n\n#### `--letsencrypt`\n\nInstallation with a Let's Encrypt free certificate. Ex. `--ssl --letsencrypt`. See [installation modes](#1-lets-encrypt-certificate).\n\n#### `--owncertificate`\n\nInstallation with an own SSL/TLS certificate. Ex. `--ssl --owncertificate`. See [installation modes](#2-own-ssltls-certificate).\n\n#### `--domain`\n\nDefine your domain. Ex. `--domain=my-domain.com` or `--domain=192.168.1.10`.\n\n#### `--email`\n\nEmail address for Let's Encrypt certificate. Ex. `--email=email@my-domain.com`.\n\n#### `--clean`\n\nClean the existing EspoCRM installation and start a new one. This option can be used if you have already installed EspoCRM. Ex. `--clean`.\n\n#### `--public-ip`\n\nNote: For HTTP mode only.\n\nIndicate a public IP address that will be used for EspoCRM installation. Ex. `--public-ip`.\n\n#### `--private-ip`\n\nNote: For HTTP mode only.\n\nIndicate a private (local) IP address that will be used for EspoCRM installation. Ex. `--private-ip`.\n\n#### `--db-root-password`\n\nDefine your own MySQL root password instead of the automatically generated one. Ex. `--db-root-password=my-password`.\n\n#### `--db-password`\n\nDefine your own MySQL password for EspoCRM installation. Ex. `--db-password=my-password`.\n\n#### `--admin-username`\n\nDefine a username of your EspoCRM administrator. Ex. `--admin-username=admin`.\n\n#### `--admin-password`\n\nDefine a password of EspoCRM administrator. Ex. `--admin-password=admin-password`.\n\n#### `--command`\n\nUpdate the `command.sh` for the existing installation. Ex. `--command`.\n\n#### `--backup-path `\n\nA path for the backup. Ex. `--backup-path =\"/backup\"`.\n\n## Server management\n\nThe operation of EspoCRM consists of several services, such as `nginx`, `mariadb`, `daemon`.\n\nIn order to update the command tool, see [update the command.sh](#update-the-commandsh).\n\n### Help\n\nIn order to display a list of available commands.\n\n```\nsudo /var/www/espocrm/command.sh help\n```\n\n### Status of services\n\n```\nsudo /var/www/espocrm/command.sh status\n```\n\n### Restart services\n\n```\nsudo /var/www/espocrm/command.sh restart\n```\n\n### Start services\n\n```\nsudo /var/www/espocrm/command.sh start\n```\n\n### Build and start services\n\nIn order to apply changes in `docker-compose.yml`.\n\n```\nsudo /var/www/espocrm/command.sh build\n```\n\n### Stop services\n\n```\nsudo /var/www/espocrm/command.sh stop\n```\n\n### EspoCRM rebuild\n\n```\nsudo /var/www/espocrm/command.sh rebuild\n```\n\n### EspoCRM upgrade\n\n```\nsudo /var/www/espocrm/command.sh upgrade\n```\n\n### EspoCRM logs\n\n```\nsudo /var/www/espocrm/command.sh logs\n```\n\n### Backup\n\nCreate a full backup of EspoCRM.\n\n```\nsudo /var/www/espocrm/command.sh backup \"BACKUP_DIRECTORY\"\n```\n\nAn example: `sudo /var/www/espocrm/command.sh backup /var/www/espocrm-backup`.\n\n### Restore\n\nRestore the backup created by the [backup](#backup) command.\n\n```\nsudo /var/www/espocrm/command.sh restore \"BACKUP_ARCHIVE\"\n```\n\nAn example: `sudo /var/www/espocrm/command.sh restore \"/var/www/espocrm-backup/2024-01-01_142051.tar.gz\"`.\n\n### Restore on a fresh server\n\nRestore the backup created by the [backup](#backup) command.\n\n#### 1. Configure the environment\n\n```\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh --environment\n```\n\n#### 2. Restore a backup\n\n```\nsudo /var/www/espocrm/command.sh restore \"BACKUP_ARCHIVE\"\n```\n\nAn example: `sudo /var/www/espocrm/command.sh restore \"/var/www/espocrm-backup/2024-01-01_142051.tar.gz\"`.\n\n#### Restore troubleshooting\n\nIn order to fix the `Error response from daemon: network external not found`, run:\n\n```\nsudo bash install.sh --network\n```\n\nand then run the `Step 2` again.\n\n### Clean\n\nDelete old and unnecessary files.\n\n```\nsudo /var/www/espocrm/command.sh clean\n```\n\n### Import SQL dump\n\nImport the database from the SQL dump created by `mariadb-dump`, `mysqldump`, `phpMyAdmin`, etc.\n\n```\nsudo /var/www/espocrm/command.sh import-sql \"PATH/DB.sql\"\n```\n\nAn example: `sudo /var/www/espocrm/command.sh import-sql \"/var/www/espocrm-backup/db.sql\"`.\n\n### Import SQL dump for one / several tables\n\nImport the database with enabled `DROP TABLE` statement in the SQL dump created by `mariadb-dump`, `mysqldump`, `phpMyAdmin`, etc.\n\n```\nsudo /var/www/espocrm/command.sh import-sql --skip-drop \"PATH/DB.sql\"\n```\n\nAn example: `sudo /var/www/espocrm/command.sh import-sql \"/var/www/espocrm-backup/db.sql\" --skip-drop`.\n\n### Export a database into the SQL dump\n\nExport the database structure and data into a .sql dump.\n\n```\nsudo /var/www/espocrm/command.sh export-sql \"PATH\"\n```\n\nAn example: `sudo /var/www/espocrm/command.sh export-sql \"/var/www/espocrm-backup\"`.\n\n### Export a database table into the SQL dump\n\nExport the single database table structure and data into a .sql dump.\n\nNotice: the database tables have different names than Entities. Ex. `TargetList` entity has the `target_list` table.\n\n```\nsudo /var/www/espocrm/command.sh export-table-sql \"PATH\" \"TABLE_NAME\"\n```\n\nAn example: `sudo /var/www/espocrm/command.sh export-table-sql \"/var/www/espocrm-backup\" account`.\n\n### Certificate generation\n\nGenerate a new Let's Encrypt certificate. It can be used to create a certificate for the first time or after a domain change.\n\n```\nsudo /var/www/espocrm/command.sh cert-generate\n```\n\n### Certificate renewal\n\nRenew an existing Let's Encrypt certificate. It can be used in crontab to automatically renewal.\n\n```\nsudo /var/www/espocrm/command.sh cert-renew\n```\n\n### Apply a domain change\n\nApplying a domain change described [here](#change-a-domain-name).\n\n```\nsudo /var/www/espocrm/command.sh apply-domain\n```\n\n### Enable automatic certificate renewal\n\nNote: This item is relevant only for the Let's Encrypt mode.\n\nEnable automatic certificate renewal. This should be done after moving to another server only.\n\n```\nsudo /var/www/espocrm/command.sh cert-cron-add\n```\n\n### Disable automatic certificate renewal\n\nNote: This item is relevant only for the Let's Encrypt mode.\n\nDisable automatic certificate renewal. This command should be run after changing the installation mode (ex. to own SSL certificate).\n\n```\nsudo /var/www/espocrm/command.sh cert-cron-remove\n```\n\n### Add a cronjob for VoIP Integration connector\n\nAdd a cronjob for a VoIP Integration extension after configuring the connector (ex. Asterisk).\n\n```\nsudo /var/www/espocrm/command.sh voip-cron-add CONNECTOR\n```\n\nwhere `CONNECTOR` is your connector ID, ex. `Asterisk`.\n\n### Remove a cronjob for VoIP Integration connector\n\nRemove a cronjob for a VoIP Integration extension after disabling the connector (ex. Asterisk).\n\n```\nsudo /var/www/espocrm/command.sh voip-cron-remove CONNECTOR\n```\n\nwhere `CONNECTOR` is your connector ID, ex. `Asterisk`.\n\n## Data\n\n### Structure\n\n```\n.\n├── data\n│   ├── espocrm\n│   ├── mariadb\n│   └── nginx\n├── docker-compose.yaml\n├── command.sh\n```\n\n### Storage location\n\nAll data are stored at:\n\n```\n/var/www/espocrm\n```\n\n## Installation modes\n\n### 1. Let's Encrypt certificate\n\nThis certificate is a free of charge and can be used by providing an email address.\n\n### 2. Own SSL/TLS certificate\n\nIf you need a high-security connection, you have to use your own SSL/TLS certificate. In this mode, EspoCRM will be installed with dummy certificates which should be replaced by real ones.\n\nPost installation steps:\n\n1\\. Go to your server directory `/var/www/espocrm/data/nginx/ssl/cert/`.\n\n2\\. Replace the following certificates with your own:\n\n- fullchain.pem\n- privkey.pem\n\n**Important!**\nYour own certificates have to substitute the existing certificates and must have the same names.\n\n3\\. Restart nginx server:\n\n```\n/var/www/espocrm/restart.sh espocrm-nginx\n```\n\n### 3. HTTP mode\n\nThis mode is recommended to use only if you don't have a domain name or want to use your IP address as a domain name.\n\n## Changing installed mode\n\nAll the actions can be applied to already installed EspoCRM instance.\n\n### From HTTP to Own SSL/TLS certificate\n\n```\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh --ssl --owncertificate --domain=my-espocrm.com\n```\n\n### From HTTP to Let's Encrypt certificate\n\n```\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh --ssl --letsencrypt --domain=my-espocrm.com --email=email@my-domain.com\n```\n\n### From Own SSL/TLS certificate to Let's Encrypt certificate\n\n```\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh --ssl --letsencrypt --domain=my-espocrm.com --email=email@my-domain.com\n```\n\n### Manually (advanced users only)\n\n1\\. Stop your existing EspoCRM instance.\n\n```\nsudo /var/www/espocrm/command.sh stop\n```\n\n2\\. Rename your existing directory:\n\n```\nmv /var/www/espocrm /var/www/espocrm-old\n```\n\n3\\. Run the installer in the required mode, e.g. `Let's Encrypt certificate` mode:\n\n```\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh --ssl --letsencrypt --domain=my-espocrm.com --email=email@my-domain.com\n```\n\n4\\. Copy your existing data to a new installation:\n\n```\nrm -rf /var/www/espocrm/data/espocrm\nrm -rf /var/www/espocrm/data/mariadb\ncp -rp /var/www/espocrm-old/data/espocrm /var/www/espocrm/data\ncp -rp /var/www/espocrm-old/data/mariadb /var/www/espocrm/data\n```\n\n5\\. Update your `/var/www/espocrm/docker-compose.yml` file. You have to copy your existing options from `/var/www/espocrm-old/docker-compose.yml` for the services:\n- `espocrm-db`\n- `espocrm`\n\n6\\. Restart services via the command:\n\n```\nsudo /var/www/espocrm/command.sh restart\n```\n\n7\\. Login as administrator and update your new `Site URL` in Administration > Settings.\n\n## Logs\n\n### Nginx logs\n\n```\n/var/www/espocrm/data/nginx/logs\n```\n\n### EspoCRM logs\n\n```\n/var/www/espocrm/data/espocrm/data/logs\n```\n\n## Update the command.sh\n\nIn order to load the latest version of the `command.sh`, run the command:\n\n```\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh --command\n```\n\n## Modify PHP settings\n\nThis can be achieved by mounting the PHP configuration file and restarting the container.\n\n1\\. Login via terminal to your server and open EspoCRM directory `/var/www/espocrm`:\n\n```\ncd /var/www/espocrm\n```\n\n2\\. Create the PHP configuration file:\n\n```\nmkdir -p data/php; \\\nnano data/php/espocrm.ini\n```\n\nwith the content:\n\n```\nexpose_php = Off\ndisplay_errors = Off\ndisplay_startup_errors = Off\nlog_errors = On\nmemory_limit=256M\nmax_execution_time=180\nmax_input_time=180\npost_max_size=30M\nupload_max_filesize=30M\ndate.timezone=UTC\n```\n\nthen press `Ctrl + 0` and `Ctrl + X`\n\n3\\. Mount the created PHP configuration file to the container:\n\n```\nsudo nano docker-compose.yml\n```\n\nadd `./data/php/espocrm.ini:/usr/local/etc/php/conf.d/espocrm.ini` option for `espocrm` container as displayed below:\n\n```\nespocrm:\n  ...\n  volumes:\n    - ./data/espocrm:/var/www/html\n    - ./data/php/espocrm.ini:/usr/local/etc/php/conf.d/espocrm.ini\n  ...\n```\n\nthen press `Ctrl + 0` and `Ctrl + X`\n\n4\\. Restart the container to apply the changes:\n\n```\nsudo ./command.sh restart espocrm\n```\n\n## Modify PHP-FPM settings\n\nThis can be achieved by mounting the PHP-FPM configuration file and restarting the container.\n\n1\\. Login via terminal to your server and open EspoCRM directory `/var/www/espocrm`:\n\n```\ncd /var/www/espocrm\n```\n\n2\\. Create the PHP-FPM configuration file:\n\n```\nmkdir -p data/php/fpm; \\\nnano data/php/fpm/zzz-espocrm.conf\n```\n\nwith the content:\n\n```\n[www]\npm.max_children = 30\n```\n\nthen press `Ctrl + 0` and `Ctrl + X`\n\n3\\. Mount the created PHP-FPM configuration file to the container:\n\n```\nsudo nano docker-compose.yml\n```\n\nadd `./data/php/fpm/zzz-espocrm.conf:/usr/local/etc/php-fpm.d/zzz-espocrm.conf` option for `espocrm` container as displayed below:\n\n```\nespocrm:\n  ...\n  volumes:\n    - ./data/espocrm:/var/www/html\n    - ./data/php/fpm/zzz-espocrm.conf:/usr/local/etc/php-fpm.d/zzz-espocrm.conf\n  ...\n```\n\nthen press `Ctrl + 0` and `Ctrl + X`\n\n4\\. Restart the container to apply the changes:\n\n```\nsudo ./command.sh restart espocrm\n```\n\n## Modify Nginx settings\n\n1\\. Login via terminal to your server and open EspoCRM directory `/var/www/espocrm`:\n\n```\ncd /var/www/espocrm\n```\n\n2\\. Edit the file `./data/nginx/conf.d/default.conf.template`\n\n```\nsudo nano ./data/nginx/conf.d/default.conf.template\n```\n\n3\\. Restart the container to apply the changes:\n\n```\nsudo ./command.sh restart espocrm-nginx\n```\n\n## Change a domain name\n\n1\\. Login via terminal to your server and open EspoCRM directory `/var/www/espocrm`:\n\n```\ncd /var/www/espocrm\n```\n\n2\\. Find and replace the old domain name with the new one in the file `./docker-compose.yml`\n\n```\nsudo nano ./docker-compose.yml\n```\n\nOptions to change:\n\n1. `NGINX_HOST`.\n2. `ESPOCRM_CONFIG_SITE_URL`.\n3. `command` under the `espocrm-certbot` service (required only for the letsencrypt mode).\n\n3\\. Run the command:\n\n```\nsudo ./command.sh apply-domain\n```\n\nNote: You have to clear your browser cache for this change to take effect.\n\n## Installer migration from v1 to v2\n\n!!! note\n\n    If your MySQL container is not running or restarting, check the [Troubleshooting](#troubleshooting) section.\n\n1\\. Export the MySQL database from the corresponding Docker container:\n\n```\nsudo mkdir -p /var/www/backup\ncd /var/www/backup\nsudo docker exec -i espocrm-mysql /usr/bin/mysqldump -uroot -pYOUR_ROOT_PASSWORD espocrm > db.sql\n```\n\nNotes:\n\n- Replace the YOUR_ROOT_PASSWORD with your MySQL root password.\n\n2\\. Copy `data` and `custom` folders from *espocrm* directory:\n\n```\nsudo cp -a /var/www/espocrm/data/espocrm/data /var/www/backup/data\nsudo cp -a /var/www/espocrm/data/espocrm/custom /var/www/backup/custom\n```\n\n3\\. Install a fresh EspoCRM by a script:\n\n```\ncd ~\nwget -N https://github.com/espocrm/espocrm-installer/releases/latest/download/install.sh\nsudo bash install.sh --db-root-password=YOUR_ROOT_PASSWORD --db-password=YOUR_ESPOCRM_DB_PASSWORD --admin-password=YOUR_ADMIN_PASSWORD --clean\n```\n\nNotes:\n\n- Replace the YOUR_ROOT_PASSWORD with your MySQL root password.\n- Replace the YOUR_ESPOCRM_DB_PASSWORD with your MySQL espocrm user password.\n- Replace the YOUR_ADMIN_PASSWORD with your EspoCRM admin user password.\n  \n4\\. Stop the services:\n\n```\nsudo /var/www/espocrm/command.sh stop\n```\n\n5\\. Replace `data` and `custom` folders in the */var/www/espocrm/data/espocrm* directory with the previously exported ones.\n\n```\nsudo rm -rf /var/www/espocrm/data/espocrm/data\nsudo rm -rf /var/www/espocrm/data/espocrm/custom\nsudo cp -a /var/www/backup/data /var/www/espocrm/data/espocrm\nsudo cp -a /var/www/backup/custom /var/www/espocrm/data/espocrm\n```\n\n6\\. Replace `'host' => 'espocrm-mysql'` line with `'host' => 'espocrm-db'` one in the */var/www/espocrm/data/espocrm/data/config-internal.php* file.\n\n7\\. Start the services:\n\n```\nsudo /var/www/espocrm/command.sh start\n```\n\n8\\. Import previously exported database to MariaDB container:\n\n```\nsudo /var/www/espocrm/command.sh import-sql /var/www/backup/db.sql\n```\n\n9\\. Make a rebuild:\n\n```\nsudo /var/www/espocrm/command.sh rebuild\n```\n\n10\\. Log in to your instance and check if everything is working well.\n\n## Troubleshooting\n\nIf after upgrading the EspoCRM instance with the [upgrade](#espocrm-upgrade) command you get error 500 in your instance and there is nothing in the logs that could be related to this error, one of the reasons could be a MySQL version upgrade (upgrades automatically). \n\n!!! warning\n\n    Make sure that your instance is using MySQL database and not MariaDB one. If it is MariaDB, then the error solution will not work for you in case of using MariaDB database.\n\nTo solve this problem and gain access to the instance, follow these steps:\n\n1\\. Stop the services:\n\n```\nsudo /var/www/espocrm/command.sh stop\n```\n\n2\\. In */var/www/espocrm/docker-compose.yaml* file, remove the following line:\n\n```\ncommand: --default-authentication-plugin=mysql_native_password\n```\n\n3\\. Insert the following line in the same place and save changes:\n\n```\ncommand: --mysql-native-password=ON\n```\n\n4\\. Build and start the services:\n\n```\nsudo /var/www/espocrm/command.sh build\n```\n"
  },
  {
    "path": "docs/administration/installation.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Installation\n\n### Requirements\n\nEspoCRM can run on most hosting providers that support PHP and a MySQL, MariaDB, or PostgreSQL database. See the [server configuration](server-configuration.md) article for more information.\n\n### 1. Download EspoCRM installation package\n\nTo get the latest version of EspoCRM, follow the [download page](http://www.espocrm.com/download/) link.\n\n### 2. Upload EspoCRM files to your server\n\nOnce download is complete, upload the package to your web server.\nTo upload it, you can use SSH, FTP or the hosting administration panel.\nExtract the archive to your public web server directory (e.g. `public_html`, `www`).\n\n!!! note\n\n    If you have only FTP access, you need to extract the archive before uploading to your web server.\n\n### 3. Create database for EspoCRM\n\nUsing your hosting administration panel, or CLI, create a new database and a database user.\n\nGrant privileges to the database user. The user must have permission to modify the database schema and full access to read and write data. Alternatively, you can also use the root user if it's a local setup.\n\n### 4. Run EspoCRM installation wizard\n\nIn the browser, open an URL that corresponds to the location where EspoCRM files were extracted (e.g. `https://yourdomain.com/espo` or `https://yourdomain.com` if you extracted to the root).\n\nIf you see the screen below, you have the *file permission* issue.\nYou need to execute the displayed command in the terminal via SSH to set the correct permissions.\nIt should be `755` for directories, `644` for files, and `775` for the `data` directory.\nAlso, make sure that you have the correct _owner_ and _group_. In most cases it's `www-data:www-data`. More info about permissions is available [here](server-configuration.md#required-permissions-for-unix-based-systems).\n\n![1](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/installation/1.png)\n\nIf you see the following screen, the permission are correct and you can start installation.\n\n![2](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/installation/2.png)\n\nIn the next step, enter details of your newly created database.\n\nFurther, you will be asked to specify a desired username and password for an admin user, some system settings (date formats, default timezone, currency, etc.). Optionally, you can configure SMTP credentials for system emails.\n\n!!! note\n\n    All these parameters can be changed in the application after installation.\n\nIn the end, the installation wizard will propose to configure cron in your system. It can be done with `crontab -e` command in Linux or _Windows Tasks Scheduler_ in Windows. See more about cron jobs [here](jobs.md).\n\nWe hope you enjoy EspoCRM.\n"
  },
  {
    "path": "docs/administration/jobs.md",
    "content": "# Jobs\n\nJobs are tasks executing in the background. They handle operations like sending notifications, mass mailing, syncing, cleanup, etc.\n\nIn this article:\n\n* [Scheduled jobs](#scheduled-jobs)\n* [Setting up (cron & daemon)](#setting-up)\n* [Running jobs in parallel processes](#running-jobs-in-parallel-processes)\n* [Parameters](#parameters)\n* [Running jobs in CLI](#running-jobs-in-cli)\n* [Tips](#tips)\n\n## Scheduled jobs\n\nScheduled jobs are intended for recurring job execution. They are available at Administration > Scheduled Jobs. Scheduling for a specific job can be configured using the crontab notation.\n\n```\n* * * * *\n| | | | |\n| | | | |\n| | | | +---- Day of the Week   (range: 1-7, 1 standing for Monday)\n| | | +------ Month of the Year (range: 1-12)\n| | +-------- Day of the Month  (range: 1-31)\n| +---------- Hour              (range: 0-23)\n+------------ Minute            (range: 0-59)\n```\n\nIf you want a job to be run as often as possible, you need to set the scheduling to `* * * * *`.\n\n## Setting up\n\nThere are two job processing setup options:\n\n* [Crontab](#cron)\n* [Daemon](#daemon)\n\nFor both, it's **highly recommended** to turn on processing jobs **in parallel** processes: Administration > Job Settings > Jobs Run in Parallel.\n\n!!! note\n\n    Parallel processing is not supported in a Windows environment.\n\n### Cron\n\nThe Cron is easy to configure, it's supported by most hosting providers. See how to configure cron [here](server-configuration.md#setting-up-crontab).\n\nIn Unix systems, the cron is supposed to be run not more often than once a minute. It's possible to overcome this limitation by adding multiple crontab actions with different delays:\n\n```\n* * * * * /usr/bin/php -f /path/to/espo/cron.php > /dev/null 2>&1\n* * * * * sleep 15; /usr/bin/php -f /path/to/espo/cron.php > /dev/null 2>&1\n* * * * * sleep 30; /usr/bin/php -f /path/to/espo/cron.php > /dev/null 2>&1\n* * * * * sleep 45; /usr/bin/php -f /path/to/espo/cron.php > /dev/null 2>&1\n```\n\nThe command that runs cron.php may vary depending on your server environment. You need to replace `/path/to/espo/` with the actual path to your instance.\n\n### Daemon\n\nDaemon setup is available only in Unix-like operating systems. Requires *pcntl* and *posix* PHP extensions (usually available by default).\n\nCommand to start the daemon using **nohup**:\n\n```\nnohup php /path/to/espocrm/daemon.php &\n```\n\n#### Using Systemd\n\nService configuration file: `/etc/systemd/system/espocrm-daemon.service`\n\nConfiguration (file content):\n\n```\n[Unit]\nDescription=EspoCRM Daemon Service\nRequires=mysql.service\nAfter=mysql.service\n\n[Service]\nType=simple\nRestart=always\nRestartSec=5\nStartLimitInterval=0\nUser=www-data\nExecStart=/usr/bin/php /path/to/espocrm/daemon.php\nStandardError=/path/to/espocrm/data/logs/daemon.log\n\n[Install]\nWantedBy=default.target\n```\n\nCommand to get the service to start on boot:\n\n```\nsystemctl enable espocrm-daemon.service\n```\n\nCommand to start the service:\n\n```\nsystemctl start espocrm-daemon.service\n```\n\n## Running jobs in parallel processes\n\n!!! note\n\n    It's **highly recommended** to enable running jobs in parallel processes.\n\nBy default, jobs are executed one by one, which may cause situations when one job blocks the execution of the next job for some time (usually, it's not more than one minute). To avoid this, it's possible to configure the system to run jobs in parallel processes. The parameter enabling this behavior is available under: Administration > Job Settings.\n\nRequires *pcntl* and *posix* extensions. Some server configurations may restrict the ability to run child processes. Windows is not supported.\n\n## Parameters\n\nThe administrator can configure job parameters under: Administration > Job Settings.\n\n#### Jobs Max Portion\n\nIt may be reasonable to increase the **Jobs Max Portion** parameter when the number of users in your CRM is increased. It defines the maximum number of jobs that can be processed in a single cron (or daemon) run. By default, it's set to *15*.\n\n#### Force UTC Time Zone\n\nIf not checked, the default time zone (set in Administration > Settings) is used for job scheduling. It's highly recommended to have this parameter unchecked. This parameter was introduced to mitigate a migration burden when time zone support was introduced for jobs.\n\n## Running jobs in CLI\n\nTo run a specific job manually in CLI\n\nCommand:\n\n```\nphp command.php run-job JobName\n```\nwhere JobName is an internal name of the job you want to run.\n\n\n!!! example\n\n    ```\n    php command.php run-job Cleanup\n    php command.php run-job ProcessMassEmail\n    ```\n\nJobs available out of the box:\n\n* CheckEmailAccounts – fetches emails for personal email accounts;\n* CheckInboundEmails – fetches emails for group email accounts;\n* Cleanup – performs cleanup, completely deletes removed records;\n* ProcessMassEmail – sends mass emails;\n* ProcessWebhookQueue – sends webhooks;\n* SendEmailNotifications\n* SendEmailReminders\n* SubmitPopupReminders\n* ControlKnowledgeBaseArticleStatus\n\nTo print all available jobs run:\n\n```\nbin/command app-info --jobs\n```\n\nSome jobs (CheckEmailAccounts, CheckInboundEmails) require specifying `--target-id` and/or `--target-type` options.\n\n!!! example\n\n    ```\n    bin/command run-job CheckEmailAccounts --target-id={email_account_id}\n    ```\n\n## Tips\n\n### Jobs stuck in running state\n\nIf a process that is running a job is terminated manually before completion, the job will remain in the *Running* status for some time until the system marks it as *Failed*. When such a situation occurs for a scheduled job, it will prevent next runs from being scheduled until the hanging job is resolved. You can manually remove that problem job to resolve the problem. Under Administration > Jobs, find the job with the status *Running* and remove it.\n\nNote that this situation is more common during development and testing, and rarely occurs in production.\n\nThe period after the hanging running job changes its status to *Failed* is controlled by the [config parameter](https://docs.espocrm.com/administration/config-params/#jobs-daemon) *jobPeriod*.\n\n## See also\n\n* [Custom scheduled job](../development/scheduled-job.md)\n"
  },
  {
    "path": "docs/administration/layout-manager.md",
    "content": "# Layout Management\n\nThe Layout Manager provides the ability to customize the appearance of detail, edit, list views as well as search filters and fields for mass-update forms. Layouts for a specific entity type can be accessed from Administration > Entity Manager.\n\nIn this article:\n\n* [Layouts](#layouts)\n* [Different layouts for teams & portals](#different-layouts-for-teams-portals)\n* [Custom list layouts](#custom-list-layouts)\n\n## Layouts\n\n* [List](#list)\n* [Detail](#detail)\n* [List (small)](#list-small)\n* [Detail (small)](#detail-small)\n* [Bottom Panels](#bottom-panels)\n* [Search Filters](#search-filters)\n* [Mass Update](#mass-update)\n* [Side Panels](#side-panels)\n* [Kanban](#kanban)\n* [Side Panel Fields](#side-panel-fields)\n* [Additional layouts](#additional-layouts)\n\n### List\n\nThe main layout for the list view. It defines columns and their parameters.\n\n![List](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/layout-manager/list.png)\n\nAvailable parameters for columns are listed below.\n\n#### Width\n\nA column width in percent or pixels. Empty means auto-width.\n\n!!! note\n\n    It's recommended to have one column without width specified.\n\n#### Link\n\nIf checked, then a field value will be displayed as a link pointing to the detail view of the record. Usually, it is used for *Name* fields.\n\n#### Not Sortable\n\nDisables the ability to sort the column.\n\n#### Align\n\nAlign the column to the left or to the right.\n\n### Detail\n\nThe main layout for the detail and edit views. It defines panels, rows and cells. Cells contain fields.\n\nThe row can contain 1, 2, 3 or 4 cells. To add a row with single cell, you need to add a new row and click on a minus sign on any cell.\n\n![Detail](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/layout-manager/detail.png)\n\nEdit panel parameters by clicking a pencil icon on the panel. It's possible to specify a label, color (style), conditions making a panel visible, group panels in tabs (as of v7.2).\n\nTo enable detail view tabs, you need to check the *Tab-break* for panels. Enable it for panels you want to be first in a tab. All following panels will be in the same tab till the next closest tab-break panel. Specify a *Tab Label* for tab-break panels.\n\n!!! note\n\n    The *Hidden* panel parameter is not fully compatible with tabs. It's not recommended to have both tab-breaks and hidden panels on the same layout.\n\n### List (Small)\n\nThe list layout for relationship panels. Also, it can be used in other places where it's reasonable to display lists in the narrow view.\n\n### Detail (Small)\n\nThe detail view for quick create, quick view and quick edit forms.\n\n### Bottom Panels\n\nPanels displayed in the bottom of the detail view. These are Relationship panels, the Stream panel and other panels defined for a concrete entity type. Panels can be re-ordered and grouped by tabs.\n\nAvailable parameters are listed below.\n\n#### Style\n\nThe color of the panel.\n\n#### Sticked\n\nThe panel will be sticked to the previous panel w/o a gap.\n\n#### Conditions making panel visible\n\nDynamic-logic conditions that determine whether the panel is visible.\n\n### Search Filters\n\nThe list of fields available in the list view to search by.\n\n### Mass Update\n\nThe list of fields available in the Mass Update form.\n\n\n### Side Panels\n\nSide panels for Detail, Edit, Detail Small, Edit Small forms. Provides the ability to hide or re-order panels. Panels can be colorized by the Style parameter. You can define dynamic-logic conditions that will determine whether the panel is visible.\n\nParameters are listed below.\n\n#### Style\n\nThe color of the panel.\n\n#### Sticked\n\nThe panel will be sticked to the previous panel w/o a gap.\n\n#### Conditions making panel visible\n\nDynamic-logic conditions that determine whether the panel is visible.\n\n### Kanban\n\nAvailable for entity types with the enabled Kanban view.\n\n### Side Panel Fields\n\nThe list of fields displayed in the top side panel. By default, there are *Assigned User* and *Teams* fields.\n\n!!! warning\n\n    Avoid having the same field added in both the Side Panel Fields layout and the Detail layout. It won't function properly.\n\n### Additional layouts\n\nSome entity types contain additional layouts: Convert Lead, List for Account and others.\n\n## Different layouts for teams & portals\n\n*Layout Sets* provide the ability to have different layouts for teams & portals.\n\nAn admin can create a Layout Set record where they will define specific layouts that will differ from standard ones (which are defined in the Entity Manager). Layout sets are available at Administration > Layout Sets.\n\nA Team and Portal have the *Layout Set* link fields.\n\nFor internal users (*regular* & *admin*), a Layout Set is applied through the *Default Team* (User > Default Team > Layout Set). The Team should have the Layout Set specified. That team should be set as a *Default Team* for the User.\n\nFor *portal* users, the Layout Set is applied through the *Portal* record.\n\nA Layout Set can also be specified for a specific User in the *Layout Set* field. Only *regular* and *admin* users have this field available. \n\n!!! note\n\n    You need to clear cache (Administration > Clear Cache) after configuring layout sets.\n\n## Custom list layouts\n\n*As of v8.0.*\n\nAn admin can create custom list layouts. These layouts can then be selected for specific relationship panels (at Administration > Entity Manager > {Entity Type} > Relationships).\n"
  },
  {
    "path": "docs/administration/ldap-authorization-for-ad.md",
    "content": "# LDAP authorization for Active Directory\n\nExample of configuration LDAP authorization for the Active Directory server. The full guide to configuring LDAP authorization is described [here](ldap-authorization.md).\n\n- Host: `espo.local`\n- Port: `389`\n- Full User DN: `cn=LDAP User,cn=espo-users,ou=users,dc=espo,dc=local`\n- Password: `******`\n- Username Attribute: `sAMAccountName`\n- User ObjectClass: `person`\n- Account Canonical Form: `Principal` or `Username`\n- Bind Requires DN: `no`\n- Base DN: `cn=espo-users,ou=users,dc=espo,dc=local`\n- Account Domain Name: `espo.local`\n- Account Domain Name Short: `ESPO`\n- Create User in EspoCRM: `yes`\n- User First Name Attribute: `givenName`\n- User Last Name Attribute: `sn`\n- User Title Attribute: `title`\n- User Email Address Attribute: `mail`\n- User Phone Number Attribute: `telephoneNumber`\n\n\n![1](../_static/images/administration/ldap-authorization/ldap-configuration-for-ad.png)\n"
  },
  {
    "path": "docs/administration/ldap-authorization-for-openldap.md",
    "content": "# LDAP authorization for OpenLDAP\n\nExample of configuration LDAP authorization for OpenLDAP server. The full guide to configuring LDAP authorization is described [here](ldap-authorization.md).\n\n- Host: `espo.local`\n- Port: `389`\n- Full User DN: `cn=LDAP User,cn=espo-users,ou=users,dc=espo,dc=local`\n- Password: `******`\n- Username Attribute: `uid`\n- User ObjectClass: `inetOrgPerson`\n- Account Canonical Form: `Dn`\n- Bind Requires DN: `yes`\n- Base DN: `cn=espo-users,ou=users,dc=espo,dc=local`\n- Create User in EspoCRM: `yes`\n- User First Name Attribute: `givenName`\n- User Last Name Attribute: `sn`\n- User Title Attribute: `title`\n- User Email Address Attribute: `mail`\n- User Phone Number Attribute: `telephoneNumber`\n\n![1](../_static/images/administration/ldap-authorization/ldap-configuration.png)\n"
  },
  {
    "path": "docs/administration/ldap-authorization.md",
    "content": "# LDAP Authorization\n\n* [LDAP configuration](#ldap-configuration)\n* [Active Directory configuration](ldap-authorization-for-ad.md)\n* [OpenLDAP configuration](ldap-authorization-for-openldap.md)\n* [Troubleshooting](#troubleshooting)\n\n## LDAP configuration\n\nIn this guide, we will show how to configure LDAP authorization for EspoCRM.\n\nGo to your LDAP server and create a base DN for the EspoCRM users like:\n\n```\ncn=espo-users,ou=users,dc=espo,dc=local\n```\n\nWe have to create a system user that will have access to the users DN (“cn=espo-users,ou=users,dc=espo,dc=local”). So, the full DN for this system user will be:\n\n```\ncn=LDAP User,cn=espo-users,ou=users,dc=espo,dc=local\n```\n\nNow, we can add LDAP user to access EspoCRM. E.g. Espo Tester with the username “tester” inside the “cn=espo-users,ou=users,dc=espo,dc=local” DN. Note: to be able to use this login format for EspoCRM, you have to specify the “Username Attribute” and “Base DN” options.\n\nThen, go to EspoCRM Authentication settings in the Administrator panel, select the `LDAP` method and fill in the LDAP details:\n\n![1](../_static/images/administration/ldap-authorization/ldap-configuration.png)\n\n* Host – LDAP IP or host name.\n* Port – connection port.\n* Auth – access credentials for the LDAP server:\n* Full User DN – the full system user DN which allows searching other users.\n    * Password – the password to access the LDAP server.\n    * Security – SSL or TSL protocol.\n* Username Attribute – The attribute to identify the user.\nE.g. for Active Directory: \"userPrincipalName\" or \"sAMAccountName\",for OpenLDAP: \"uid\" .\n* Account Canonical Form – the type of your account canonical form. There are 4 options:\n    * `Dn` – the form in the format `CN=tester,CN=Espocrm,DC=company,DC=com`.\n    * `Username` – the form `tester`.\n    * `Backslash` – the form `COMPANY\\tester`.\n    * `Principal` – the form `tester@company.com`.\n* User ObjectClass – ObjectClass attribute for searching users. E.g. for Active Directory: \"person\", for OpenLDAP: \"inetOrgPerson\".\n* Bind Requires Dn – if there is a need to format the username in the DN form.\n* Base Dn – the default base DN which is used for searching users.\n* User Login Filter – the filter which allows you to restrict users who are able to use EspoCRM. E.g. `memberOf=cn=espoGroup,cn=espo-users,ou=users,dc=espo,dc=local`.\n* Try Username Split – the option to split a username with the domain.\n* Opt Referrals – if referrals should be followed to the LDAP client.\n* Create User in EspoCRM – this option allows EspoCRM to create a user from the LDAP.\n* User First Name Attribute – LDAP attribute which is used to determine the user’s first name.\n* User Last Name Attribute – LDAP attribute which is used to determine the user’s last name.\n* User Title Attribute – LDAP attribute which is used to determine the user title.\n* User Email Address Attribute – LDAP attribute which is used to determine the user’s email address.\n* User Phone Number Attribute – LDAP attribute which is used to determine the user’s phone number.\n* User Teams – Teams for created user. For more, see user profile.\n* User Default Team – Default team for created user. For more, see user profile.\n* Use LDAP Authentication for Portal Users – Allow portal users to use LDAP authentication instead of Espo authentication.\n* Default Portals for a Portal User – Default Portals for created Portal User.\n* Default Roles for a Portal User – Default Roles for created Portal User.\n\n!!! note\n\n    For the **first** LDAP user login (both system and portal) the `Create User in EspoCRM` parameter should be checked. Otherwise it won't be able to login.\n\nNow, go to the login page and enter user credentials.\n\n![2](../_static/images/administration/ldap-authorization/ldap-login.png)\n\nUser has been authenticated and automatically created in the EspoCRM.\n\n## Troubleshooting\n\n### Error: 0x31 (Invalid credentials; 80090308: LdapErr: DSID-0C09041C, comment: AcceptSecurityContext error, data 52e, v4563)\n\nThis error occurs when the wrong `Account Canonical Form` or `Username Attribute` are specified.\nThe correct values are:\n- Account Canonical Form: `Principal` or `Username`. \n- Username Attribute: `sAMAccountName`\n\nThe full Active Directory configuration, see in the [documentation](ldap-authorization-for-ad.md).\n"
  },
  {
    "path": "docs/administration/log.md",
    "content": "---\nsearch:\n  boost: 3\n---\n\n# Log\n\n## Default log\n\nBy default, the application log files are automatically created in the directory `{ESPO_ROOT}/data/logs/`.\n\n## Parameters\n\nLog parameters are available in the file `data/config-internal.php`.\n\nParameters example:\n\n```\n'logger' => [\n  'level' => 'NOTICE', // DEBUG, INFO, NOTICE, WARNING, ERROR\n  'maxFileNumber' => 30,\n  'printTrace' => true, // to print an exception backtrace,\n  'sql' => true, // log SQL queries\n  'sqlFailed' => true, // log failed SQL queries\n  'databaseHandler' => true, // the log will be available in the admin UI\n  'databaseHandlerLevel' => 'NOTICE', // overrides the level for the database handler\n],\n```\n\n## Trace printing\n\nParameter: `printTrace`.\n\nIf enabled, the backtrace will be printed to the log when an exception is occurred. Note that in some cases an exception is caught and handled within the application, the trace won't be printed in this case.\n\n!!! warning\n\n    It is not recommended to enable trace printing on the production environment, as it may expose sensitive data to the log.\n\n## Admin UI\n\nParameter: `databaseHandler`.\n\n*As of v8.3.*\n\nIt may be convenient to check the logs right from the application UI. The log is available under: Administration > App Log. By default, this feature is disabled – log entries are not created in the database table.\n\nTo make log records available in the admin UI, set the *databaseHandler* parameter to true. \n\n!!! note\n\n    Some log entries may be not available from the UI. For example, those that happened during upgrade or before database connection was established.\n\n## SQL queries\n\nParameter: `sql`.\n\n*As of v7.4.*\n\n!!! note\n\n    Not to be enabled on production.\n\nIf the parameter *sql* is set to true, all executed SQL queries will be printed to the log. Requires *INFO* or *DEBUG* level. \n\nIf *sql* is set to true, and the log level is *NOTICE* or higher, than only failed queries will be logged. As of v8.2.\n\nIf the parameter `sqlFailed` is true, failed queries will be printed.\n\n## Handlers\n\nEspoCRM uses [Monolog](https://github.com/Seldaek/monolog) library for logging. The library is shipped with many handlers. Developer can also create custom handlers.\n\nIt's possible to configure the list of handlers Espo should use for logging.\n\nIn `data/config-internal.php`:\n\n```\n'logger' => [\n  'level' => 'NOTICE',\n  'handlerList' => [\n    [\n      'className' => 'Espo\\\\Core\\\\Log\\\\Handler\\\\EspoRotatingFileHandler',\n      'params' => [\n        'filename' => 'data/logs/espo.log',\n      ],\n      'level' => 'NOTICE',\n      'formatter' => [\n        'className' => 'Monolog\\\\Formatter\\\\LineFormatter',\n        'params' => [\n          'dateFormat' => 'Y-m-d H:i:s',\n        ],\n      ],\n    ],\n    [\n      'loaderClassName' => 'Espo\\\\Core\\\\Log\\\\EspoRotatingFileHandlerLoader',\n      'params' => [\n        'filename' => 'data/logs/test-warning.log',\n      ],\n      'level' => 'WARNING',\n    ],\n  ],\n],\n```\n\nHandlers can be defined with a handler class name or a loader class name. The loader class instantiates a handler class.\nThis allows initializing constructor parameters for the handler. It can be helpful if you need to pass some parameters to the handler's constructor and these parameters cannot be resolved with the DI mechanism.\nThe loader class must implement `Espo\\Core\\Log\\HandlerLoader` interface. It's possible to pass dependencies to the loader via the DI mechanism.\n\n!!! note\n\n    By specifying `handlerList` in the config, the default handler stops from being used.\n\nYou can find the list of handlers supported by Monolog [here](https://github.com/Seldaek/monolog/tree/main/src/Monolog/Handler).\n"
  },
  {
    "path": "docs/administration/maps.md",
    "content": "# Maps\n\nEspoCRM supports Google Maps out of the box.\n\n## Google Maps\n\n### API Key\n\nTo use Google Maps, you need to specify the API Key (at Administration > Integration > Google Maps). Geocoding API, Maps JavaScript API, Maps Static API must be enabled in Google Maps Platform.\n\n### Map ID\n\nCreate a Map ID under Google Cloud Console > Map Management.\n\n## Showing map for address field\n\n### As a field in detail view\n\nEvery *Address* field has a corresponding *Map* field. You need to add it to the *Detail* layout. Administration > Entity Manager > {Entity Type} > Layouts > Detail > Drag & Drop Map field. You can make the cell wide using the minus sign. \n\nYou can also configure the height of your field. Administration > Entity Manager > {Entity Type} > Fields > find the map field and click on it > edit the height and save.\n\n### In modal dialog\n\nAdministration > Entity Manager > {Entity Type} >  {needed address field} (e.g. *Billing Address*) > Check **View Map Button** and save.\n\n*View Map* button should appear under the address field on the detail view. Note, that the address should contain either a city or postal code.\n\n## Printing in PDF\n\n*googleMapsImage* helper is available for printing Google Maps in PDF.\n\nUsage (in PDF Template):\n\n```\n{{googleMapsImage}}\n```\n\nPrinting a specific address field:\n\n```\n{{googleMapsImage field='shippingAddress'}}\n```\n\nPrinting a specific address:\n\n```\n{{googleMapsImage city='New York' country='United States'}}\n```\n\nAvailable options:\n\n* field\n* size - `300x300`\n* zoom - integer value\n* language\n* street\n* city\n* state\n* postalCode\n* country\n\nExample:\n\n```\n{{googleMapsImage size='400x400'}}\n```\n"
  },
  {
    "path": "docs/administration/moving-to-another-server.md",
    "content": "# Moving EspoCRM to another server\n\nFollow these steps to move EspoCRM to another server.\n\n### Step 1. Backup files\n\nOpen a file manager or log in via SSH to archive all available files from the EspoCRM directory. See [more details](backup-and-restore.md#step-1-back-up-files).\n\n### Step 2. Backup your database\n\nThe data stored in the database (MySQL, MariaDB or PostgreSQL) should be backed up. Follow this [recommendation](backup-and-restore.md#step-2-back-up-database).\n\n### Step 3. Copy files and database backups to another server\n\nCopy the backups of files and your database to a new server.\n\n### Step 4. Unarchive backup files\n\nTo unarchive the backup files, you can use Archive Manager or this [instruction](backup-and-restore.md#step-1-unarchive-backup-files).\nNote: Files need to be placed in the web-server directory.\n\n### Step 5. Configure the server\n\nConfigure the new server based on the recommendations [here](server-configuration.md).\n\n### Step 6. Correct permissions\n\nSet proper permissions and file ownership, see [here](server-configuration.md#required-permissions-for-unix-based-systems).\n\n### Step 7. Import your database backup\n\nFirst, you have to create a new database with a user in MySQL/MariaDB/PostgreSQL. To import your database from the backup, follow these [instructions](backup-and-restore.md#step-3-import-database-dump).\n\n### Step 8. Correct EspoCRM configurations\n\nAfter successfully importing and configuring the server, correct EspoCRM config parameters in the files `data/config-internal.php` and  `data/config.php`.\n\nDatabase connection settings:\n\n```php\n'database' => [\n    'driver' => 'pdo_mysql',\n    'dbname' => 'YOUR_DATABASE_NAME',\n    'user' => 'YOUR_USER',\n    'password' => 'YOUR_DATABASE_PASSWORD',\n    'host' => 'localhost',\n    'port' => '',\n],\n```\n\nSite URL, if your domain name (URL) has changed:\n\n```php\n'siteUrl' => 'https://new-link.com',\n```\n\nDefault file owner (only if the new web server has a different user/group):\n\n```php\n'defaultPermissions' => [\n    'user' => 'www-data',\n    'group' => 'www-data',\n],\n```\n\nwhere `www-data` is your web-server user.\n\n### Step 9. Setup a crontab\n\nSetup a [crontab](server-configuration.md#setting-up-crontab).\n\n!!! note\n\n    it should be configured under your web-server user.\n\nNow, your EspoCRM instance is running on the new server.\n\n## Misc\n\n### MariaDB to MySQL migration\n\nWhen migrating from MariaDB to MySQL, a database dump incompatibility arises. The problem is that MariaDB supports default values for TEXT column but MySQL does not. To solve this problem, you can manually remove default values for text columns in the dump file. Usually, there are not many.\n"
  },
  {
    "path": "docs/administration/multiple-assigned-users.md",
    "content": "# Multiple Assigned Users\n\n*As of v9.0.*\n\nMultiple assigned users can be enabled for custom entity types and for certain built-in entity types. Enable it at: Administration > Entity Manager > {Entity Type} > Edit > check *Multiple Assigned Users* and save.\n\n!!! important\n\n    Existing assigned users which are already set in the *Assigned User* field won't be transferred to the new *Assigned Users* field after enabling multiple assigned users.\n\nThe maximum number of assigned users allowed per record can be set at: Administration > Entity Manager > {Entity Type} > Fields > Assigned Users > Max Item Count. By default, it's set to 10.\n\nAfter enabling Multiple Assigned Users, you may need to replace the Assigned User field with the Assigned Users field in the following layouts: Mass Update, Search Filters, and List.\n"
  },
  {
    "path": "docs/administration/nginx-server-configuration.md",
    "content": "# Nginx server configuration for EspoCRM\n\nThese instructions are supplementary to the [server configuration](server-configuration.md) guidelines. Note that all configuration settings listed here are made on an Ubuntu server.\n\n## PHP requirements\n\nTo install all necessary libraries, run these commands in a terminal:\n\n```\nsudo apt-get update\nsudo apt-get install php-mysql php-json php-gd php-zip php-imap php-mbstring php-curl php-exif php-ldap\nsudo phpenmod imap mbstring\nsudo service nginx restart\n```\n\n## Server configuration\n\nNginx config file example:\n\n```\nserver {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n\n    server_name localhost; # domain name\n\n    charset utf-8;\n    index index.html index.php;\n\n    client_max_body_size 50M;\n\n    keepalive_timeout 300;\n    types_hash_max_size 2048;\n\n    server_tokens off;\n    fastcgi_send_timeout 300;\n    fastcgi_read_timeout 300;\n\n    gzip on;\n    gzip_types text/plain text/css text/javascript application/javascript application/json;\n    gzip_min_length 1000;\n    gzip_comp_level 9;\n\n    root /path-to-espo/public; # path to public dir\n\n    location /client {\n        root /path-to-espo; # path to espocrm root dir\n        autoindex off;\n\n        location ~* ^.+\\.(js|css|png|jpg|svg|svgz|jpeg|gif|ico|tpl)$ {\n            access_log off;\n            expires max;\n        }\n    }\n\n    location = /favicon.ico { access_log off; log_not_found off; }\n    location = /robots.txt  { access_log off; log_not_found off; }\n\n    location ~ \\.php$ {\n        fastcgi_pass espocrm-php:9000;\n        include fastcgi_params;\n        fastcgi_index index.php;\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        fastcgi_param QUERY_STRING $query_string;\n    }\n\n    location /api/v1/ {\n        if (!-e $request_filename){\n            rewrite ^/api/v1/(.*)$ /api/v1/index.php last; break;\n        }\n    }\n\n    location /portal/ {\n        try_files $uri $uri/ /portal/index.php?$query_string;\n    }\n\n    location /api/v1/portal-access {\n        if (!-e $request_filename){\n            rewrite ^/api/v1/(.*)$ /api/v1/portal-access/index.php last; break;\n        }\n    }\n\n    location ~ /(\\.htaccess|\\web.config|\\.git) {\n        deny all;\n    }\n}\n```\n\nYou need to change `/path-to-espo` to the absolute path of your EspoCRM instance.\n\nWhat this config does:\n\n* sets the document root to `/path-to-espo/public/`;\n* redirects `/client/` requests to `/path-to-espo/client/` (as the *client* dir is located outside of the *public* dir);\n* adds some rewrite rules.\n\nConfig file path: `/etc/nginx/sites-available/YOUR_SITE`. If you don’t have this file, you have to create it. For this, open the terminal and run the command:\n\n```\nsudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/espocrm.conf\n```\n\nFor more information on how to configure the new virtual host on Nginx, read this [guidelines](nginx-virtual-host.md).\n\nRun this command in the terminal to check if everything is fine:\n\n```\nsudo nginx -t\n```\n\nIf so, run the command to restart the nginx server:\n\n```\nsudo service nginx restart\n```\n\n## See also\n\nTo configure a new Virtual Host on Nginx, read this [guidelines](nginx-virtual-host.md).\n"
  },
  {
    "path": "docs/administration/nginx-virtual-host.md",
    "content": "# Configuring Virtual Host on Nginx\n\nIn this guide we will show how to configure a virtual host on Nginx for EspoCRM on Ubuntu server.\n\n## Create a server block file\n\nTo create this file, open a terminal and run the command:\n\n```\nsudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/espocrm.conf\n```\n\nNow, open this file (`/etc/nginx/sites-available/espocrm.conf`) and modify the code following the format printed below (some settings may be different depending on your configuration).\n\n```\nserver {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n\n    server_name localhost; # domain name\n\n    charset utf-8;\n    index index.html index.php;\n\n    client_max_body_size 50M;\n\n    keepalive_timeout 300;\n    types_hash_max_size 2048;\n\n    server_tokens off;\n    fastcgi_send_timeout 300;\n    fastcgi_read_timeout 300;\n\n    gzip on;\n    gzip_types text/plain text/css text/javascript application/javascript application/json;\n    gzip_min_length 1000;\n    gzip_comp_level 9;\n\n    root /path-to-espo/public; # path to public dir\n\n    location /client {\n        root /path-to-espo; # path to espocrm root dir\n        autoindex off;\n\n        location ~* ^.+\\.(js|css|png|jpg|svg|svgz|jpeg|gif|ico|tpl)$ {\n            access_log off;\n            expires max;\n        }\n    }\n\n    location = /favicon.ico { access_log off; log_not_found off; }\n    location = /robots.txt  { access_log off; log_not_found off; }\n\n    location ~ \\.php$ {\n        fastcgi_pass espocrm-php:9000;\n        include fastcgi_params;\n        fastcgi_index index.php;\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        fastcgi_param QUERY_STRING $query_string;\n    }\n\n    location /api/v1/ {\n        if (!-e $request_filename){\n            rewrite ^/api/v1/(.*)$ /api/v1/index.php last; break;\n        }\n    }\n\n    location /portal/ {\n        try_files $uri $uri/ /portal/index.php?$query_string;\n    }\n\n    location /api/v1/portal-access {\n        if (!-e $request_filename){\n            rewrite ^/api/v1/(.*)$ /api/v1/portal-access/index.php last; break;\n        }\n    }\n\n    location ~ /(\\.htaccess|\\web.config|\\.git) {\n        deny all;\n    }\n}\n```\n\nYou need to change `/path-to-espo` to the absolute path of your EspoCRM instance.\n\n## Enable this server block\n\nCreate a symbolic link:\n\n```\nsudo ln -s /etc/nginx/sites-available/espocrm.conf /etc/nginx/sites-enabled/\n```\n\nRun this command to check if everything is fine:\n\n```\nsudo nginx -t\n```\n\nAnd restart Nginx server:\n\n```\nsudo service nginx restart\n```\n\n## Configure your local hosts (optional, for a local domain only)\n\nIf you added a local domain, you have to configure it on your local computer (not on the server). For Ubuntu, open the file `/etc/hosts` and add the line:\n\n```\n192.168.1.1 espocrm.local  # specify the IP address of your Nginx server\n```\n\nFor Windows, follow these [instructions](http://support.microsoft.com/kb/923947).\n"
  },
  {
    "path": "docs/administration/oidc.md",
    "content": "# OpenID Connect (OIDC) Authentication\n\n*As of v7.3.*\n\nEspoCRM supports authentication over the OIDC protocol. A user can log in to multiple systems (that your business uses) with a single account. In other words, users can authenticate to Espo using identity providers that support OpenID Connect.\n\n!!! note\n\n    EspoCRM cannot be used as an identity provider. This article is about configuring EspoCRM to use a 3rd party identity provider for authentication.\n\nFeatures:\n\n* User creation. Optional. If a user does not exist in Espo, it will be created upon the first login.\n* Team mapping. Espo teams are mapped against identity provider's groups. The Espo user is automatically associated with the corresponding teams.\n* User profile and user teams sync. Optional. On every login, the user profile data is automatically synced with the provider's data.\n* The ability to choose a claim that will be used as a username.\n* Fallback login method. The ability to use the default Espo method. Can be enabled for admins or for both regular users and admins.\n* For admins, the OIDC method can be disabled so that only the fallback method is allowed.\n* Logout redirect. When a user is logging out from Espo, the identity provider session is cleared. \n* Backchannel logout. The ability to forcibly log out a user from Espo. Available under `api/v1/backchannelLogout` API endpoint.\n\nDetails:\n\n* Espo's 2-factor authentication does not work with OIDC. Consider using 2FA of your identity provider.\n* The *userName* field length may need to be increased up to 255 in some cases (by default, Espo has the limit 50).\n* Supported signing algorithms: RS256, RS384. RS512, HS256, HS384, HS512. Developers can add implementations of other algorithms in an upgrade-safe manner.\n* *client_secret_jwt* and *private_key_jwt* [methods](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication) are not supported. You might need to enable *client_secret_post* method for providers that apply a JWT method by default (e.g. Keycloak).\n\n## Setting up\n\n1. Create an application in your identity provider.\n2. In EspoCRM at Administration > Authentication, select the *OIDC* method. Below, on the same form, a *OIDC* panel will appear.\n  * Copy the *Client ID* and the *Client Secret* from the identity provider to Espo.\n  * Copy the *Authorization Redirect URI* from Espo and add it to a corresponding field on the identity provider.\n  * Copy required endpoints (URLs) from the identity provider to Espo.\n  * Save the form in Espo.\n\n## Team mapping\n\nIf your identity provider users have groups, it's reasonable to map them against Espo teams. When an Espo user is created (upon signing in the first time) or synced, corresponding teams will be assigned to that user according to the configured team mapping.\n\nNote that instead of 'group', the provider may use terms like 'team', 'role', or another equivalent designation.\n\nYou need to specify the *Group Claim*, the [claim](https://en.wikipedia.org/wiki/JSON_Web_Token) that will be carrying the information about user groups. Some identity providers don't include the group claim in the JWT payload by default and you need to do some settings to have it.\n\n## Setting up for portals\n\n*As of v7.4.*\n\n1. Create an application in your identity provider.\n2. In EspoCRM, at Administration > Authentication Providers, create a provider.\n3. In EspoCRM, edit the Portal record, select the Authentication Provider.\n\n## Auth0\n\n1. Set the *Group Claim* to `http://www.myexample.com/roles` in Espo.\n2. Create [a rule](https://auth0.com/docs/manage-users/access-control/sample-use-cases-actions-with-authorization?_ga=2.226983773.1572279349.1664444295-1913114833.1664024344&_gl=1*1y6ck81*rollup_ga*MTkxMzExNDgzMy4xNjY0MDI0MzQ0*rollup_ga_F1G3E656YZ*MTY2NDQ1ODY2Mi44LjEuMTY2NDQ2MzU5OS40OS4wLjA.#add-user-roles-to-tokens) to include the roles claim in the JWT.\n\n## Debugging\n\nSet the *DEBUG* or *INFO* mode for the [log](log.md). More information will be printed to the log. It can be useful to see what values is sent in JWT tokens (printed to the log), especially when configuring the team mapping.\n\n## Additional config parameters\n\nCan be set manually in `data/config.php`.\n\n* oidcAuthorizationMaxAge – integer;\n* oidcJwksCachePeriod – string  (default: `'10 minutes'`);\n"
  },
  {
    "path": "docs/administration/passwords.md",
    "content": "# Passwords\n\n## New users\n\nWhen an administrator creates a new user, there are two options for password generation:\n\n* Let the user set the password by leaving the password field empty. The user must have a valid email address. Upon creation, an email with a unique link will be sent to the user.\n* Specify the password for the user. In this case, checking 'Send Email with Access Info to User' will send the password in an email to the user. This method is not recommended due to security concerns.\n\n## Existing users\n\nAn administrator can send a password change link to an existing user. The user will receive an email with a link where they can specify a new password. Note that this option is not available for users without an email address.\n\n![Menu](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/passwords/user-menu.png)\n\nThe administrator can also generate a new password for the user from the menu. The new password will be sent in an email. This way is not recommended as it's not secure.\n\n## Password recovery\n\nUsers can reset their password from the login form by clicking 'Forgot Password?' link. They will be promted to enter their username and email address. If the credentials are correct, they will receive an email with a unique link. By following the link, they will be able to specify a new password. Note that the link will be active only for 3 hours and the user is not permitted to send new password change requests during that period.\n\n![Menu](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/passwords/login-form.png)\n\nAn administrator can disable the ability to recover passwords at Administration > Authentications > Passwords. It can be disabled for all users, for admin users or for internal users.\n\n## Password strength\n\nAn administrator can configure password strength settings at Administration > Authentications > Passwords. Available parameters:\n\n* Minimum password length;\n* Number of letters required in password;\n* Password must contain letters of both upper and lower case;\n* Number of digits required in password.\n\n## See also\n\n* [Password config parameters](config-params.md#passwords)\n"
  },
  {
    "path": "docs/administration/performance-tweaking.md",
    "content": "# Performance Tweaking\n\n## Recommendations\n\n* SSD is preferred over HDD.\n* Dedicated server is preferred over shared.\n* More RAM can be helpful if your database grows.\n\n## Database indexes\n\nBy default, EspoCRM has some pre-defined indexes. As your database gets bigger, it's reasonable to create new indexes. Exactly which indexes are needed depends on how you use CRM and how you customized it: what custom fields are created, default record orders are set, reports are often run, searches are usually performed, etc.\n\n* You need indexes for fields that are used for a default order.\n* You need indexes for fields that are often used in filters (reports & regular searches).\n\nSee the article on [how to create indexes](../development/db-indexes.md).\n\n## Database choice\n\nFilters by teams, relations, multi-enums perform faster in MariaDB and PostgreSQL than in MySQL (as of the date we performed tests).\n\n## MySQL and MariaDB parameters\n\n#### innodb_buffer_pool_size\n\nIt's recommended to set a value that is about 70% of your RAM.\n\n#### sort_buffer_size\n\nYou may consider increasing this param to speed up ORDER BY or GROUP BY. [See more](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_sort_buffer_size).\n\n#### innodb_log_file_size\n\nShould be large enough. [See more](https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_log_file_size).\n\n#### innodb_flush_log_at_trx_commit\n\nWe recommend to set it to `2`.\n\n## Misc\n\n### Disabling total count on list view\n\nIt is relevant if there are a lot of records of a specific entity type in the database. In this case, it can be reasonable to disable displaying the record count in the list view for that entity type, since the COUNT function may perform very slow in MySQL and MariaDB.\n\nTo disable: Administration > Entity Manager > {entity type} > Edit > check *Disable record count*.\n\n### Use full-text search\n\nCreate [full-text search](../user-guide/text-search.md#full-text-search) indexes for large tables. It will improve record lookup.\n\n## PHP configuration\n\n### Preloading\n\nYou can use a [preloading](https://www.php.net/manual/en/opcache.preloading.php). The file `preload.php` is available at the root directory.\n\nUsing preloading is not likely to bring a significant performance boost. The database usually is the bottleneck in applications like CRM.\n\n!!! important\n\n    Preloading must be disabled before upgrading and extension installation.\n"
  },
  {
    "path": "docs/administration/phone-numbers.md",
    "content": "# Phone Numbers\n\n## International phone numbers\n\nThe international phone numbers functionality can be enabled or disabled at Administration > Settings. When enabled, all phone number values are stored in the international format, e.g. *+111111111111*.\n\nFeatures:\n\n* A user is able to select country code when entering a number in a phone number field.\n* Appropriate formatting is applied when a phone number is displayed.\n* Validation is applied when saving a phone number, not allowing to save a not valid number.\n\nIt is possible to define preferred country codes at Administration > Settings. This will avoid the need to enter the same country code when operating in a specific region.\n\nWhen importing records, there is the ability to specify a regional telephone code, so that values in a regional format will be automatically converted to international. The same functionality exists for the Lead Capture feature.\n\n![Phone numbers](../_static/images/administration/phone-numbers/phone-numbers.png)\n"
  },
  {
    "path": "docs/administration/portal/apache-configuration.md",
    "content": "# Configuring Portal in Apache\n\nIt's possible to be able to access to the Portal by a different URL. You need to set the *Custom URL* field in the Portal record. For example, you can use your domain name `portal.my-company.com` to access the Portal.\n\n\nConfig example:\n\n```\nDocumentRoot /path_to_espo/public/portal/\nAlias /client/ /path_to_espo/client/\nAlias /api/v1/ /path_to_espo/public/api/v1/\n\n<Directory /path_to_espo/>\n    AllowOverride None\n</Directory>\n\n<Directory /path_to_espo/public/>\n    AllowOverride All\n</Directory>\n\n<IfModule mod_rewrite.c>\n    RewriteEngine On\n\n    RewriteRule .* - [E=ESPO_PORTAL_ID:{PORTAL_ID}]\n</IfModule>\n```\n\n* Replace `/path_to_espo/` with the absolute path of your EspoCRM instance (e.g. it can be `/var/www/html/`).\n* Replace `{PORTAL_ID}` with the ID of your Portal. The ID can be obtained from the address bar in your web browser when you open the detail view of the Portal record. E.g. in the URL `https://my-espocrm-url.com/#Portal/16b9hm41c069e6j24`, *16b9hm41c069e6j24* is the Portal record ID.\n\nWhat this configuration does:\n\n* Sets the *public/portal* directory as a root directory.\n* Creates an alias to redirect */client/* requests to the *client* directory which is located outside of our webserver root.\n* Creates an alias to redirect */api/v1/* requests to the respective directory.\n* Disables *.htaccess* in the Espo root directory (as it's not needed).\n* Enables *.htaccess* in the *public* directory (which defines rewrite rules for API requests).\n* Enables *mod_rewrite*.\n* Makes the portal ID to be passed in an environment variable to let Espo know what Portal to start (as there can be multiple Portals in Espo).\n\nNote that if you use [WebSocket](../websocket.md), you also need to setup a [proxy](../websocket.md#apache) for the portal URL.\n"
  },
  {
    "path": "docs/administration/portal/nginx-configuration.md",
    "content": "# Configuring Portal in Nginx\n\nIt's possible to be able to access to the Portal by a different URL. You need to set the Custom URL field in the Portal record. For example, you can use your domain name `portal.my-company.com` to access the Portal.\n\nConfig example:\n\n```\nserver {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n\n    server_name localhost; # domain name\n\n    charset utf-8;\n    index index.html index.php;\n\n    client_max_body_size 50M;\n\n    keepalive_timeout 300;\n    types_hash_max_size 2048;\n\n    server_tokens off;\n    fastcgi_send_timeout 300;\n    fastcgi_read_timeout 300;\n\n    gzip on;\n    gzip_types text/plain text/css text/javascript application/javascript application/json;\n    gzip_min_length 1000;\n    gzip_comp_level 9;\n    \n    root /path-to-espo/public/portal; # path to `public/portal` dir\n\n    location /client {\n        root /path-to-espo; # no trailing slash needed\n        autoindex off;\n\n        location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|tpl)$ {\n            access_log off;\n            expires max;\n        }\n    }\n\n    location /api {\n        root /path-to-espo/public; # path to `public` dir\n        autoindex off;\n\n        location ~ \\.php$ {\n            fastcgi_pass espocrm-php:9000;\n            include fastcgi_params;\n            fastcgi_index index.php;\n            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n            fastcgi_param QUERY_STRING $query_string;\n        }\n\n        location /api/v1/portal-access {\n            if (!-e $request_filename){\n                rewrite ^/api/v1/portal-access/(.*)$ /api/v1/portal-access/index.php last; break;\n            }\n        }\n    }\n\n    location ~ \\.php$ {\n        fastcgi_pass espocrm-php:9000;\n        include fastcgi_params;\n        fastcgi_index index.php;\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        fastcgi_param QUERY_STRING $query_string;\n\n        fastcgi_param ESPO_PORTAL_ID {PORTAL_ID}; # portal ID\n        fastcgi_param ESPO_PORTAL_IS_CUSTOM_URL \"true\";\n    }\n\n    location ~ /(\\.htaccess|\\web.config|\\.git) {\n        deny all;\n    }\n}\n```\n\n* Replace `path-to-espo` with the absolute path to your EspoCRM instance.\n* Replace `{PORTAL_ID}` with the ID of your Portal. The Portal record ID can be obtained from the address bar of your web browser when you open the detail view of the Portal record. For example, in `https://my-espocrm-url.com/#Portal/16b9hm41c069e6j24`, 16b9hm41c069e6j24 is the Portal record ID.\n"
  },
  {
    "path": "docs/administration/portal.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Portal\n\nThe Portal feature provides the ability to access specific CRM data and functions for your customers and partners. An administrator can create multiple Portals. Each Portal can have its own settings, dashboard, user list and access control settings.\n\nTo create a Portal, follow Administration > Portals > *Create Portal*.\n\nPortal fields (parameters):\n\n* *Is Active*. If not checked, the Portal won't be available for anybody.\n* *Is Default*. Means that the Portal will be available by shorter URL: `https://YOUR_ESPO_URL/portal`.\n* *Roles*. Specify one or multiple Portal Roles that will be applied to Users logged into the Portal. More information about the Portal Roles is below.\n* *Tab List*. Tabs which will be shown in the navigation bar in the Portal.\n* *Dashboard Layout*. Specify dashlets that will be displayed on the home page of the Portal. Note that Portal Users can't configure their dashboard.\n* *URL*. Read-only field that displays the link you can access the Portal with.\n* *Layout Set*. Provides the ability to use different layouts from the Portal. See [more](layout-manager.md#different-layouts-for-teams-portals).\n\nIn this article:\n\n* [Portal users](#portal-users)\n* [Portal roles](#portal-roles)\n* [Access to portal](#access-to-portal)\n* [See also](#see-also)\n\n## Portal users\n\nAdministrators can create portal users.\n\n1. Administration > Portal Users.\n2. Click *Create Portal User* button.\n3. Select Contact the Portal User will be linked with or *Proceed w/o Contact*\n4. Fill needed fields on the form and click *Save*.\n\nA Portal User should be linked to a Portal record in order to be able to access that Portal.\n\nPortal Users can have one or multiple additional *Portal Roles*. These roles will be merged with roles specified for a Portal.\n\nPortal Users can have a specific *Dashboard Layout*. It allows certain users to have a specific layout that differs from the default Portal's layout.\n\n## Portal roles\n\nPortal Roles are similar to regular Roles in EspoCRM but with a few distinctions.\n\n* not-set ‒ Denies access.\n* own ‒ Records created by the user. E.g. a portal user created some case and this case is owned by this user.\n* account ‒ Records related to the account the portal user is related to.\n* contact ‒ Records related to the contact the portal user is related to.\n\nFor custom entity types, to be able to use *account* and *contact* access levels, you need (as of v9.0):\n\n1. To have relationships between your entity type and Account/Contact.\n2. To select these relations in the *ACL Account Link* and *ACL Contact Link* parameters at Administration > Entity Manager > {Entity Type} > Edit.\n\nThe *Assigned User* and *Teams* fields are read-only for portal users.\n\nPortal Roles can be applied to:\n\n* Portal ‒ all users of the portal will receive this role (multiple roles applied to one Portal are merged into one);\n* Portal User ‒ to grant certain users specific permissions.\n\n### Example\n\n*Portal Users should be able to create Cases, view Cases related to their Account; they also should be able to view Knowledge Base.*\n\n1. Open the *Create Portal Role* form (Administration > Portal Roles > Create Role).\n2. Enable access to Cases, set: *create – yes, read – account, edit – no, delete – no, stream – account*.\n3. Enable access to Knowledge Base, set: *create – no, read – account, edit – no, delete – no*.\n4. Edit the Portal record (Administration > Portals). Select your portal role in Roles field and then save.\n\n## Access to portal\n\nYou can find the URL for your Portal in the *URL* field of the Portal record.\n\nIt's possible to use server configuration tools (such as mod_rewrite) to be able to access the portal by a different URL. For this case, you need to fill in the *Custom URL* field. Note that using a different subdomain is recommended way. Prefer it over accessing the portal through the */portal* directory. See the server configuration guidelines:\n\n* [Apache configuration](portal/apache-configuration.md)\n* [Nginx configuration](portal/nginx-configuration.md)\n\n## See also\n\n* [Quick tour](https://app.supademo.com/demo/cmgajngej3dxj2noml5li5gm3)\n"
  },
  {
    "path": "docs/administration/roles-management.md",
    "content": "---\nsearch:\n  boost: 2\ntags:\n  - roles\n---\n\n# Role Management\n\nIn this article:\n\n* [Overview](#overview)\n* [Permissions by default](#permissions-by-default)\n* [Actions](#actions)\n* [Levels](#levels)\n* [Example](#example)\n* [Special Permissions](#special-permissions)\n* [Collaborators](#collaborators)\n* [See also](#see-also)\n\n## Overview\n\nRoles are used to grant or restrict access for users. An administrator can manage Roles under Administration > Roles. Each Role defines access to specific areas (scopes).\n\nOne User can have multiple Roles applied. Roles can be set in the User record (the *Roles* field) and/or be inherited from the User's Teams.\n\nWhen a User has multiple Roles, these Roles will be merged in a way that a more permissive rule will have a higher priority over a less permissive. This enables the ability to flexibly manage access level control.\n\nIt's possible to see what permissions are applied to a certain User by clicking the *Access* button on the user's detail view.\n\n![1](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/roles-management/scope-level.png)\n\n!!! note\n\n    By default, users can **delete self-assigned records** that they have created during a specific period of time. It is possible to disable this ability at Administration > Settings > Allow to remove created records.\n\n## Permissions by default\n\nBy default, Users have minimal access levels restricting almost everything. You need to assign Roles to grant Users specific access levels.\n\n### Baseline role\n\n*As of v9.2.*\n\nIt's possible to designate one role as a baseline. This role will be applied for all internal users. Other roles assigned to a user will grant permissions on top of the baseline.\n\nThe baseline role can be set under: Administration > Settings > Access.\n\n## Actions\n\n* Create – ability to create records;\n* Read – ability to view records (on the list and detail views);\n* Edit – ability to update records;\n* Delete – ability to remove records;\n* Stream – ability to see a record's stream.\n\n## Levels\n\nListed from more permissive to less permissive.\n\n* yes\n* all\n* team\n* own\n* no\n\n## Example\n\nWe have a Team 'Sales'. That Team has a single Role 'Salesperson' (the *Roles* field of the Team). All Users from this Team will obtain the 'Salesperson' Role (as all team roles are automatically applied to users of the team).\n\nThe 'Salesperson' Role is defined in the following way:\n\nLead:\n\n```\ncreate – yes\nread – team\nedit – own\ndelete – no\nstream – team\n```\n\nOpportunity:\n\n```\ncreate – yes\nread – team\nedit – own\ndelete – no\nstream – team\n```\n\nUsers of the 'Sales' Team:\n\n* Can create new Leads/Opportunities.\n* Are able to read only those Leads/Opportunities that are related to the 'Sales' Team (through the *Teams* field of a record).\n* Are able to edit only those Leads/Opportunities that they are assigned to.\n* Can't remove any Lead/Opportunity.\n* Have access to the Stream of Leads/Opportunities that are related to the 'Sales' Team.\n\nWe want to give more rights to a certain User who holds a Sales Manager position in the company. This employee needs to have the ability to read/edit/delete all records related to the 'Sales' Team. We need to add that user to the 'Sales' Team. We also need to create a new role 'Sales Manager' and select this Role for that User (the *Roles* field of the User).\n\nThe 'Sales Manager' role is defined in the following way:\n\nLead:\n\n```\ncreate - yes\nread – team\nedit – team\ndelete – team\nstream - team\n```\n\nOpportunity:\n\n```\ncreate – yes\nread – team\nedit – team\ndelete – team\nstream – team\n```\n\nOur sales manager User will be able to manage all Leads/Opportunities related to the 'Sales' Team. Under the hood this User have two roles ('Salesperson' and 'Sales Manager') merged into one in a way that a more permissive level suppresses less permissive.\n\n## Special Permissions\n\n### Assignment Permission\n\nSet this parameter to restrict the ability to re-assign records to another User and/or Teams. If you set the parameter to *team*, users will be able to assign record only to Users from their own Teams. If you set it to *no*, users won't be able to assign at all.\n\nThis parameter also defines whether the User is able to post to the Stream of other Users and other Teams.\n\n### User Permission\n\nAllows to view:\n\n* Stream of other Users;\n* which access to a specific record other Users have.\n\n!!! warning\n\n    Allow this permission only to privileged users. A user with this permission is designated as a supervisor and is authorized to view data available to their subordinates, in some cases bypassing record-level access control.\n\n### User Calendar Permission\n\n*As of v9.0.*\n\nAllows to view Calendars of other users.\n\n!!! warning\n\n    A user with this permission is designated as a calendar supervisor and is authorized to view calendar data available to their subordinates, in some cases bypassing record-level access control.\n\n### Portal Permission\n\nDefines access to portal information, the ability to post messages to Portal Users.\n\nUsers with the Portal Permission can manage followers of a specific record. Only Portal Users can be managed.\n\n### Group Email Account Permission\n\nDefines access to Group Email Accounts, the ability to send emails from a group SMTP.\n\n### Export Permission\n\nDefines whether a User have the ability to export records.\n\n### Mass Update Permission\n\nDefines whether users have the ability to mass-update records.\n\n### Data Privacy Permission\n\nAllows to erase personal data.\n\n### Follower Management Permission\n\nAllows to manage followers of specific records. Users will be able to add and remove followers. Can be restricted to Users of own Teams.\n\n### Message Permission\n\nAllows to send stream messages to other Users. (as of v8.0)\n\n### Audit Permission\n\nAllows to view the Audit Log. (as of v8.2)\n\n### Mention Permission\n\nAllows to mention other Users in the Stream. (as of v8.3)\n\n### Lock Permission\n\nAllows to lock and unlock records. (as of v10.0)\n\n## Field Level Security\n\nAllows to control access for specific fields.\n\nBy default, a User can read all fields if they can read the record. A User can edit any field if one can edit the record. You can restrict access to specific fields using the Field Level Security.\n\nIn the edit view of a Role record in the Field Level section, click plus icon next to a specific scope, then select a needed field. Then, you will be able to specify the access level for *read* and *edit* actions. There are two options: *yes* and *no*.\n\n![2](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/administration/roles-management/field-level-secutiry.png)\n\n## Collaborators\n\nSee more about the Collaborators feature in the [separate article](collaborators.md).\n\nUsers added as collaborators to a record obtain *read* and *stream* access, provided their access level, as defined by Roles, is other than *no*.\n\nAccess prerequisites:\n\n- Assignment Permission is required to be able to add a user to collaborators.\n- Edit access to a record is required to be able to add collaborators.\n\n## See also\n\n* [Roles quick tour](https://app.supademo.com/embed/cmls03z6a1dl01189pv9nrmb9)\n* [Security roles management in EspoCRM](https://www.espocrm.com/tips/security-roles/)\n* [Multiple assigned users](multiple-assigned-users.md)\n"
  },
  {
    "path": "docs/administration/security.md",
    "content": "# Security recommendations\n\n## Password strength\n\n❗ Important.\n\nConfigure password strength parameters (at Administration > Authentication). The minimum recommended password length is at least 10 characters (or 8 if 2FA is mandatory). Require digits, and both upper case and lower case letters.\n\n## 2-factor authentication\n\n❗ Important.\n\nEnable 2FA for users. Require regular users to set up 2FA with the corresponding parameter. Can be enabled at Administration > Authentication.\n\n## Don't use admin user\n\nDon't use an admin user for everyday work. Use a regular user instead.\n\n## Disable password recovery for admins\n\nCan be done at Administration > Authentication. If you lost admin access and want to recover your password, set 'passwordRecoveryForAdminDisabled' to *false* in `data/config.php`.\n\n## Auth token expiration\n\nConsider decreasing *Auth Token Max Idle Time*. Additionally, you can also specify *Auth Token Lifetime*.\n\n## Restrict upgrade via UI\n\n❗ Important.\n\nRestrict the ability to upgrade and upload extensions via the UI. Set `'adminUpgradeDisabled' => true` in `data/config-internal.php`.\n\n!!! note\n\n    By default, upgrades and extensions can be installed via the admin UI. Installed extensions can run code, which may pose a security risk.\n\n## IP address whitelist\n\nConsider specifying an IP address whitelist. Parameters are available at: Administration > Authentication > Access.\n"
  },
  {
    "path": "docs/administration/server-configuration.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Server Configuration for EspoCRM\n\nEspoCRM can be installed on:\n\n* Webserver\n  * [Apache](apache-server-configuration.md)\n  * [Nginx](nginx-server-configuration.md)\n  * [IIS](iis-server-configuration.md)\n* PHP 8.3 - 8.5\n* Database\n  * MySQL 8.0 and greater\n  * MariaDB 10.3 and greater\n  * PostgreSQL 15\n\nIn this article:\n\n* [Recommendations & requirements](#recommendations-requirements)\n* [Required permissions for Unix-based systems](#required-permissions-for-unix-based-systems)\n* [Setting up crontab](#setting-up-crontab)\n* [Configuration instructions based on your server](#configuration-instructions-for-specific-web-servers)\n* [See also](#see-also)\n\n\n## Recommendations & requirements\n\n### PHP requirements\n\nEspoCRM requires PHP with the following extensions:\n\n* [pdo_mysql](https://php.net/manual/en/book.pdo.php) – for database access;\n* [gd](https://php.net/manual/en/book.image.php) (with enabled FreeType support) – to manipulate images and render avatars;\n* [openssl](https://php.net/manual/en/book.openssl.php) – to ensure the highest protection;\n* [zip](https://php.net/manual/en/book.zip.php) – to be able to upgrade EspoCRM and install extensions;\n* [mbstring](https://php.net/manual/en/book.mbstring.php);\n* [iconv](https://php.net/manual/en/book.iconv.php);\n* [curl](https://php.net/manual/en/book.curl.php) – for integrations;\n* [xml](https://php.net/manual/en/book.xml.php) – for excel export;\n* [xmlwriter](http://php.net/manual/en/book.xmlwriter.php) – for excel export;\n* [exif](https://php.net/manual/en/book.exif.php) – for a proper orientation of uploaded images;\n* [bcmath](https://www.php.net/manual/en/book.bc.php) – arbitrary precision mathematics;\n\nOptional PHP extensions that could be useful:\n\n* [zmq](http://php.net/manual/en/book.zmq.php) – for WebSocket;\n* [pcntl](http://php.net/manual/en/book.pcntl.php) – for parallel job processing and daemon (Unix-like systems only);\n* [posix](http://php.net/manual/en/book.posix.php) – for Unix-like systems;\n* [ldap](http://php.net/manual/en/book.ldap.php) – for LDAP authentication;\n* [ev](https://www.php.net/manual/en/book.ev.php) – for WebSocket, if a large number of connections is expected.\n\nRecommended minimum values in php.ini:\n\n```\nmax_execution_time = 180\nmax_input_time = 180\nmemory_limit = 256M\npost_max_size = 50M\nupload_max_filesize = 50M\n```\n\n### Database requirements\n\nEspoCRM supports MySQL,  MariaDB and PostgreSQL. There are no special requirements – the default settings work fine for EspoCRM.\n\n### Server recommendations\n\nPrefer using a VPS or a dedicated server for production EspoCRM instances. Shared hosting typically imposes some limitations. Nevertheless, Espo can run on shared hosting environments quite smoothly.\n\n## Required permissions for Unix-based systems\n\n!!! note\n\n    In most cases, permissions are set properly after extracting EspoCRM instance from the zip package. You may only need to set file ownership.\n\n### Permissions\n\nA simple setup.\n\nSet files and directories to the following permissions:\n\n* `data`, `custom`, `client/custom` – all files, directories and subdirectories should be writable (664 for files, 775 for directories, including all subdirectories and files);\n* `bin/command` – should be executable (754);\n* all other files and directories should be readable (644 for files, 755 for directories).\n\nTo set the permissions, execute these commands in the terminal:\n\n```\ncd <PATH-TO-ESPOCRM-DIRECTORY>\nfind . -type d -exec chmod 755 {} + && find . -type f -exec chmod 644 {} +;\nfind data custom client/custom -type d -exec chmod 775 {} + && find data custom client/custom -type f -exec chmod 664 {} +;\nchmod 754 bin/command;\n```\n\n### Ownership\n\nThe simplest setup is when all files are owned and group-owned by the web server user. It can be *www-data*, *daemon*, *apache*, *www*, etc.\n\n!!! note\n\n    On shared hosts, files usually should be owned and group-owned by your user account.\n\n\n\nTo set the owner and group-owner, execute these commands in the terminal:\n\n```\ncd <PATH-TO-ESPOCRM-DIRECTORY>\nchown -R <OWNER>:<GROUP-OWNER> .;\n```\n\n### Permission and ownership recommendations\n\nIn production, static application files are typically owned by the deployment user and group-owned under the web server user (e.g. *deploy-user:www-data*). Writable directories should usually be both owned and group-owned by the web server user.\n\nExample:\n\n- `data/`, `custom/Espo/Custom/` – `www-data:www-data`; directories: `770`, files: `660`;\n- everything else – `deploy-user:www-data`; directories: `750`, files: `640`;\n- `bin/command` – `deploy-user:deploy-user`; `700` (for running console commands);\n\nNote that this setup implies that upgrades and extensions cannot be installed via the admin UI (should be installed via CLI).\n\nThe last 0 in the directory's octal permissions determines that other users cannot access or traverse the directory.\n\n## Setting up crontab\n\nMore information about jobs in EspoCRM is available [here](jobs.md).\n\n### Unix-like systems\n\nTo setup crontab on Unix-like system, take the following steps:\n\n1\\. Login as administrator into your EspoCRM instance.\n\n2\\. Go to the Scheduled Jobs section in the administrator panel (Menu > Administration > Scheduled Jobs) and copy the string for the crontab. It looks like this one:\n\n```\n* * * * * /usr/bin/php -f /var/www/html/espocrm/cron.php > /dev/null 2>&1\n```\n\nYou might need to replace `/var/www/html/espocrm/` with an actual path to your instance.\n\n3\\. Open a terminal and run this command:\n\n```\ncrontab -e -u WEBSERVER_USER\n```\n\nWEBSERVER_USER can be one of the following “www”, “www-data”, “apache”, etc (depends on your webserver).\n\n4\\. Paste the copied string (from step 2) and save the crontab file (Ctrl + O, then Ctrl + X for nano editor).\n\n### Windows\n\nSee in a separate [article](cron-on-windows.md) how to set up Cron on Windows.\n\n## Configuration instructions for specific web servers\n\n* [Apache server configuration](apache-server-configuration.md)\n* [Nginx server configuration](nginx-server-configuration.md)\n* [IIS server configuration](iis-server-configuration.md)\n\n## See also\n\n* [Jobs](jobs.md)\n* [WebSocket](websocket.md)\n* [Performance tweaking](performance-tweaking.md)\n* [Installation by script](installation-by-script.md)\n"
  },
  {
    "path": "docs/administration/sms-sending.md",
    "content": "# SMS Sending\n\nEspoCRM has the built-in functionality for sending SMS, but it's not shipped with any provider implementation. The official [SMS Providers](https://github.com/espocrm/ext-sms-providers/) extension includes implementations for the following SMS providers:\n\n* Twilio\n* Spryng\n* seven\n* smstools\n* SerwerSms\n* Verimor\n* GatewayAPI\n\nOut of the box, it's possible to send SMS from a Formula script or from a PHP code. The [VoIP Integration](https://www.espocrm.com/extensions/voip-integration/) provides also the ability to send SMS through the UI (only for the Twilio provider).\n\nIn this article:\n\n* [Setting up](#setting-up)\n* [Sending with formula](#sending-with-formula)\n* [Two-Factor Authentication](#two-factor-authentication)\n* [VoIP integration for Twilio](#voip-integration-for-twilio)\n\n## Setting up\n\nDownload the extension package from the [GitHub repository](https://github.com/espocrm/ext-sms-providers/releases) (under the Assets section). Then upload and install the package in Espo at Administration > Extensions.\n\nAfter the SMS Providers extension is installed, go to Administration > SMS and select the *SMS Provider* you want to use from the dropdown list. Also, in the *SMS From Number* field, enter the number with the country code (e.g. +11111111111) from which you will be sending SMS messages.\n\nNext, go to Administration > Integrations, select your provider, and set up needed credentials and parameters.\n\n## Sending with formula\n\nIt's possible to send SMS from a formula-script with the [ext\\sms\\send](formula/ext.md#extsmssend) function.\n\n### With Workflow\n\n*Requires [Advanced Pack](https://www.espocrm.com/extensions/advanced-pack/).*\n\nWith the Workflow tool it's possible to set up Espo to SMS notification on a specific condition.\n\nCreate a Workflow rule with the needed trigger type and conditions. Add the *Execute Formula Script* action and paste the following formula-script:\n\n```\n$body = 'Hi! This is an SMS notification from EspoCRM.';\n\n// Phone number is obtained from the entity.\n$phoneNumber = phoneNumber;\n\n$smsId = record\\create(\n    'Sms',\n    'to', $phoneNumber,\n    'body', $body\n);\n\next\\sms\\send($smsId);\n```\n\n## Two-Factor Authentication\n\n[SMS 2FA](2fa.md#authentication-via-sms) is supported out of the box, but you need to have an implementation for your SMS provider (see the SMS Providers extension).\n\nNote that the *Phone* field of the user, for whom you want to set up the Two-Factor Authentication, must be filled in with at least one number.\n\n1. At Administration > Authentication, check the box *Enable 2-Factor Authentication*. Add the *SMS* value in the field *Available 2FA methods*. Save changes. \n2. At Administration > Users, select the user for which the 2FA will be configured.\n3. On the detail view of the user, click on the *Access* button and check the box *Enable 2-Factor Authentication*. Also, choose *SMS* 2FA Method in the drop down list. Click the *Apply* button.\n4. Enter the Administrator password, select a phone number that will be used for 2FA in the *Phone* dropdown list, and click the *Send Code* button.\n5. Enter the code that will be sent to the selected phone number and click the *Apply* button.\n\n## VoIP integration for Twilio\n\nThe [VoIP integration](https://www.espocrm.com/extensions/voip-integration/) allows sending and receiving Twilio SMS/MMS through the UI.\n\n!!! important\n\n    The VoIP integration does not support the SMS Providers extension. It implements Twilio SMS only.\n\nTo use Twilio Integration for receiving and making calls, SMS and MMS, first configure it according to [these instructions](https://docs.espocrm.com/extensions/voip-integration/twilio-integration-setup/). \n\nAt Administration > VoIP Routers > the phone number required for sending and receiving SMS, check the *SMS* and *MMS* boxes for those team users whom you need in the Team Users panel.\n\nAlso, you need to enable Twilio messaging geographic permissions: \n\n1. Log in to your Twilio account. \n2. Navigate to Programmable SMS > Settings > [Geo Permissions](https://www.twilio.com/console/sms/settings/geo-permissions). \n3. Enable needed countries.\n\nDo not forget to set *[Grant access to Messages](https://docs.espocrm.com/extensions/voip-integration/customization/#grant-access-to-messages)* for the required users.\n\nKeep in mind that for the Twilio Trial account you will need to add a [*Verified Phone Numbers* or *Caller ID*](https://support.twilio.com/hc/en-us/articles/223180048-Adding-a-Verified-Phone-Number-or-Caller-ID-with-Twilio).\n\nAfter that, you can proceed to the installation and configuration of the SMS Providers extension.\n"
  },
  {
    "path": "docs/administration/terms-and-naming.md",
    "content": "# Terms & Naming\n\n## Entity type\n\nAn *entity type* is a type of data, an object. For example, Account, Contact, Opportunity, Task, Knowledge Base.\n\nEntity types are named in UpperCamelCase (start with a capital letter).\n\nThe list of available entity types can be obtained at: Administration > Entity Manager > *Name* column.\n\nEntity types contain fields and links in their definitions.\n\n## Field\n\nA *field* is a unit of data. An entity defines its own set of fields. For example, name, status, createdAt, assignedUser.\n\nFields are named in lowerCamelCase (starting with a lowercase letter).\n\n!!! info\n\n    The list of available fields for a specific entity type can be obtained at: Administration > Entity Manager > {Entity Type} > Fields > *Name* column.\n\nEach field can have one or few attributes (depending on the field type).\n\nThe list of available field types can be found [here](fields.md).\n\n## Attribute\n\n* An attribute usually corresponds to a database column, provided that the attribute is storable.\n* In the REST API, JSON object keys correspond to attributes.\n* Attributes are used for accessing entity values in Formula Script.\n\n!!! info\n\n    The list of available attributes for a specific field can be obtained at: Administration > Entity Manager > {Entity Type} > View Details from the dropdown of the field.\n\nMost fields have only one attribute named the same as the field. For example, the *createdAt* field has the attribute *createdAt*. Some fields have multiple attributes.\n\nField types that have multiple attributes and their attribute naming:\n\n* Link: *fieldId*, *fieldName*\n* Link-Multiple: *fieldIds*, *fieldNames* (ids − array of IDs, names − object of ID => name pairs)\n* Link-Parent: *fieldId*, *fieldType*, *fieldName* (type is an entity type)\n* Currency: *field*, *fieldCurrency* (currency is a currency code)\n* Person Name: *firstName*, *lastName*, *middleName*, *salutationName*\n* Address: *fieldStreet*, *fieldCity*, *fieldPostalCode*, *fieldCountry*, *fieldState*\n\nWhere *field* is a name of the field.\n\nAttributes are named in lowerCamelCase (start with a lowercase letter).\n\n## Link\n\nA *link* represents a relationship with another entity.\n\nLinks are named in lowerCamelCase (start with a lowercase letter).\n\n!!! info\n\n    The list of available links for a specific entity type can be obtained at: Administration > Entity Manager > {Entity Type} > Relationships.\n\nEach relationship between two entity types is a pair of two links on both sides.\n\nLink types:\n\n* belongsTo\n* hasMany\n* hasOne\n* belongsToParent\n* hasChildren\n\nRelationship type & link types mapping:\n\n* One-to-Many: hasMany + belongsTo\n* Many-to-One: belongsTo + hasMany\n* Many-to-Many: hasMany + hasMany\n* One-to-One Right: belongsTo + hasOne\n* One-to-One Left: hasOne + belongsTo\n* Parent-to-Children: hasChildren + belongsToParent\n"
  },
  {
    "path": "docs/administration/troubleshooting.md",
    "content": "# Troubleshooting\n\nIn this article:\n\n* [Check logs](#check-logs)\n  * [Debug mode](#debug-mode)\n* [Check system requirements](#check-system-requirements)\n* [File permissions](#file-permissions)\n* [Scheduled jobs are not working](#scheduled-jobs-are-not-working)\n* [Running rebuild from CLI](#running-rebuild-from-cli)\n* [EspoCRM is not loading after upgrade](#espocrm-is-not-loading-after-upgrade)\n* [MySQL error: The server requested authentication method unknown to the client](#mysql-error-the-server-requested-authentication-method-unknown-to-the-client)\n* [Emails are not being fetched](#emails-are-not-being-fetched)\n* [Delay in fetching emails](#delay-in-fetching-emails)\n* [Admin password is lost, can't log in](#admin-password-is-lost-cant-log-in)\n* [MySQL error: MySQL can only use 61 tables in a join](#mysql-error-mysql-can-only-use-61-tables-in-a-join)\n* [MySQL error: Row size too large](#mysql-error-row-size-too-large)\n\n## Check logs\n\nThis is the most **important step** in diagnosing the problem. There are two main logs you need to check:\n\n* EspoCRM [log](log.md);\n* Webserver error log.\n\n#### EspoCRM log\n\nEspoCRM log files are located in `{ESPO_ROOT}/data/logs/` directory. Most errors are logger there.\n\n#### Webserver error log\n\n\n##### Apache\n\nThe Apache error log is usually located at `/var/log/apache2/error.log`. The location of the log file can vary in different systems.\n\n##### Nginx\n\n`/var/log/nginx/error.log`\n\n### Debug mode\n\nIn some cases, it can be reasonable to enable debug mode for the Espo logger. It will print more information to the log.\n\nTo enable debug mode for the logger, edit the file `data/config-internal.php` and set the value of the *logger.level* parameter to `DEBUG`:\n\n```\n'logger' => [\n    ...\n    'level' => 'DEBUG',\n]\n```\n\nDon't forget to revert the mode back after the problem is solved (to `WARNING` or `ERROR`).\n\n### Backtrace printing\n\nEnabling trace printing will print a backtrace to the log for every thrown exception. Can be very useful for debugging occurred errors.\n\nIn `data/config-internal.php` (or `data/config.php`):\n\n```\n'logger' => [\n    ...\n    'printTrace' => true,\n]\n```\n\n## Check system requirements\n\nAt Administration > System Requirements. It's important that you have all required PHP extensions installed.\n\n## File permissions\n\nIt's the most common issue. Because of incorrect file permissions (or ownership), the instance might not be able to write certain files (for example, cache files). You can find how to configure file permissions [here](server-configuration.md#permissions).\n\n## Scheduled jobs are not working\n\n#### Problem #1: Your crontab is not configured\n\n1\\. Login via SSH to your server.\n\n2\\. Configure your crontab by following these [steps](server-configuration.md#setting-up-crontab).\n\nNote: Crontab should be configured under web-server user, e.g. `crontab -e -u www-data`.\n\n3\\. Wait for a while and check Scheduled Jobs to see if any jobs were executed (see a Log panel).\n\n#### Problem #2. Crontab is configured, but Scheduled Jobs are not working\n\nTo make sure there are no errors when cron is running, try to run the cron command in the terminal:\n\n1\\. Login via SSH to your server.\n\n2\\. Go to the directory where EspoCRM is installed. E.g. for `/var/www/html/espocrm` directory the command is:\n\n```bash\ncd /var/www/html/espocrm\n```\n\n3\\. Run the crontab command:\n\n```bash\nphp cron.php\n```\n\nNote: It's better to execute under web-server user. If you are logged in as root, the command should be (e.g for Ubuntu):\n\n```bash\nsudo -u www-data php cron.php\n```\n\nwhere `www-data` is a web-server user.\n\n4\\. If there are no errors, check Scheduled Jobs to see if any job was executed (see a Log panel).\n\n## Running rebuild from CLI\n\nSometimes you need to run rebuild from the command-line interface, usually when the application fails to load or the log shows database-schema errors.\n\n```bash\nphp rebuild.php\n```\n\n## EspoCRM is not loading after upgrade\n\n[Check logs](#check-logs) for errors. Googling an error message may help figure out the cause of the problem.\n\nOften the problem is caused by the webserver PHP version being lower than the minimum required version.\n\nFile permissions can be set to not proper values on some shared hostings after upgrade. \n\nCheck permissions of these files:\n\n* `public/index.php`\n* `public/api/v1/index.php`\n\nThey must be 644. If any of these files have permission 664, you need to change it to 644. Use your hosting's control panel or *chmod* command.\n\n```\nchmod 644 /path/to/file\n```\n\nMore information about file permissions can be found [here](server-configuration.md#required-permissions-for-unix-based-systems).\n\n## MySQL error: The server requested authentication method unknown to the client\n\nMySQL 8.0.4 has changed a default authentication method to `caching_sha2_password` which is not supported by PHP (at the time of writing). For MySQL 8 it should be changed to `mysql_native_password` method. For a user it can be done with the query:\n\n```\nCREATE USER username@localhost identified with mysql_native_password by 'password';\n```\n\nwhere username is your MySQL user, password is your MySQL user password.\n\n## Emails are not being fetched\n\n1. Make sure [cron](server-configuration.md#setting-up-crontab) is running. You will see the error notification on the main administration page if cron is not running.\n2. Check EspoCRM log (data/logs) and server logs for errors.\n3. Check log at Administration > Scheduled Job > Check Personal Email Accounts. Make sure there are no records with failed status.\n4. Check log at Administration > Scheduled Job > Check Group Email Accounts. Make sure there are no records with failed status.\n\n## Delay in fetching emails\n\nThe following configuration will speed up your email fetching (and other background processes):\n\n1. Cron should be configured to execute once a minute or more often. More details [here](jobs.md#setting-up).\n2. The *Jobs Run in Parallel* parameter should be enabled in Administration > Jobs > Settings (in the top-right corner). More details [here](jobs.md#running-jobs-in-parallel-processes).\n\n## Admin password is lost, can't log in\n\nRun the following command in CLI:\n\n```\nphp command.php set-password [username]\n```\n\nwhere `[username]` is a user name, e.g. `admin`.\n\n## MySQL error: MySQL can only use 61 tables in a join\n\nFull error message: *General error: 1116 Too many tables; MySQL can only use 61 tables in a join*.\n\nAny of the following actions may solve the problem.\n\n1. Remove unused many-to-one and one-to-one relationships (if you have such).\n2. Disable link-multiple for some many-to-many relationships of the problem entity type.\n3. Set `noJoin` parameter (to `true`) for some *belongsTo* links. [Example](https://github.com/espocrm/espocrm/blob/7.2.7/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Campaign.json#L269).\n4. Set *currencyNoJoinMode* (`'currencyNoJoinMode' => true,` in `data/config.php`). With this mode enabled, you will need to clear Espo cache every time you change the system currency list. (as of v7.3)\n\n## MySQL error: Row size too large\n\nFull error messages (may be one of the following):\n\n1. *ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, \nnot counting BLOBs, is 65535. This includes storage overhead, check the manual. You \nhave to change some columns to TEXT or BLOBs.*\n2. *ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to \nTEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.*\n\nYou can get this error if there are too many Varchar fields in an entity type. You cannot create new fields in this case.\n\nTo fix this problem, you can try two solutions:\n\n### Solution 1. Decrease max length for some varchar fields\n\n#### Step 1. Change in definitions\n\nEdit the file `custom/Espo/Custom/Resources/metadata/entityDefs/{EntityType}.json`. Decrease *maxLength* parameter for some custom varchar fields. E.g. from 255 to 100.\n\n#### Step 2. Change columns length in database\n\nThen you need to amend the corresponding columns in your database by changing their length. You can do it manually (by running a query or via a database admin tool) or run a [hard rebuild](commands.md#hard-rebuild).\n\n#### Step 3. Rebuild\n\n*Not needed if you already run a hard rebuild.*\n\nLog in as an administrator in EspoCRM, go to Administration and click *Rebuild*. Alternatively, run rebuild via [CLI](commands.md/#rebuild).\n\n### Solution 2. Change type for some varchar fields from *Varchar* to *Text* \n\n#### Step 1. Change in definitions\n\nEdit the file `custom/Espo/Custom/Resources/metadata/entityDefs/{EntityType}.json` manually. Change definitions of some custom varchar fields from:\n\n```\n\"type\": \"varchar\",\n\"maxLength\": 150\n```\n\nto:\n\n```\n\"type\": \"text\"\n```\n\nNote that the *maxLength* value can be different for your field. You just need to remove it. Make sure that the resulting JSON is valid.\n\n#### Step 2. Rebuild\n\nLog in as administrator in EspoCRM, go to Administration and click the Rebuild link. Alternatively, rebuild via [CLI](commands.md/#rebuild).\n"
  },
  {
    "path": "docs/administration/upgrading-manually.md",
    "content": "# Upgrading Manually\n\n## Option 1. Migration\n\n!!! note\n\n    The minimal version you can upgrade from using this method is 7.1.0.\n    The minimal version you can upgrade to using this method is 8.3.0.\n\n!!! note\n\n    This method assumes that all installed third party extensions have their files placed in the `custom` and `client/custom` directories.\n\n!!! important\n\n    This methods does not perform before-upgrade checks that the regular upgrade method does. After replacing the files manually, it's possible that your system won't work due to reasons like PHP version incompatibility or customization incompatibility. The method is preferred for more experienced users.\n\nCheck all the [recommendations](https://docs.espocrm.com/administration/upgrading/#recommendations) before performing upgrade.\n\n### 1. Replace files.\n\nReplace all application files with files with files from a new version package. You need to delete all existing source files except the directories listed below.\n\nThe directories you must NOT delete:\n\n* `data`\n* `custom`\n* `client/custom`\n\nMake sure [file permissions](server-configuration.md#required-permissions-for-unix-based-systems) are correct.\n\n### 2. Run migration.\n\nRun the command:\n\n```\nbin/command migrate\n```\n\nIt will run needed prepare and after-upgrade scripts, run rebuild. The version parameter in config will be updated.\n\n## Option 2. Upgrade package\n\nManually replicating upgrade with an upgrade package. This is another option to upgrade, not related to the section above.\n\n!!! important\n\n    Only for very experienced users. It's **not recommended** way to upgrade. We do not guarantee any success if you decide to upgrade this way.\n\nIf your environment is configured properly, the regular upgrade process via CLI should work fine.\n\nIn some cases it can be more reasonable to install a fresh instance, then copy your `custom` directory, `data/upload` directory, install all needed extensions.\n\nThe following actions are the same as those that the automatic upgrade script performs when you run the *upgrade* command.\n\n## 0. Check system requirements of the new version.\n\nWhether your system suits for the new version. Sometimes we drop support of old PHP and MySQL versions.\n\n### 1. Run rebuild.\n\nMake sure no error occurred. If any error occurred it means your Espo instance is faulty and need to be fixed before upgrade.\n\n### 2. Download an upgrade package. Unzip it.\n\nFind a needed upgraded package at https://www.espocrm.com/download/upgrades/. If the needed package is not listed\nyou can try to compose an URL `https://www.espocrm.com/downloads/upgrades/EspoCRM-upgrade-{FROM}-to-{TO}.zip` by substituting the *from* and *to* versions.\nMaybe the needed file exists but not listed on the page. Note that there are no packages that skip minor versions. *6.0.10* can be upgraded to *6.1.3* in one step but cannot to *6.2.0*.\n\n### 3. Copy files from copyBefore\n\n1. Check whether the directory `copyBefore` exists in the package. If it does not exist, then skip this step.\n2. Copy all files from there to the root directory of your instance.\n3. Run rebuild.\n\n### 4. Run before-upgrade script.\n\nCheck whether the file `scripts/BeforeUpgrade.php` exists in the package. If it does not exist, then skip this step.\n\nCreate a file `BeforeUpgradeRunner.php` in the root directory of your instance:\n\n```php\n<?php\ninclude \"bootstrap.php\";\nrequire_once \"BeforeUpgrade.php\";\n\n$app = new \\Espo\\Core\\Application();\n\n(new \\BeforeUpgrade())->run(\n    $app->getContainer()\n);\n\n```\n\nCopy `scripts/BeforeUpgrade.php` to the root directory.\n\nRun `BeforeUpgradeRunner.php`.\n\nRun rebuild.\n\nRemove created files.\n\n### 5. Apply vendor files.\n\n1. Check whether `vendorFiles` directory exists in the package. If it does not exist, then skip this step.\n2. Replace the existing `vendor/autoload.php` file (in your instance) with `vendorFiles/autoload.php` (from the package).\n3. Remove folders `vendor/*` (in your instance) that are presented in the upgrade packages in `vendorFiles` directory.\n4. Copy all folders from `vendorFiles` directory (upgrade package) to `vendor` directory of your instance.\n\n### 6. Remove unneeded files.\n\n1. Open `manifest.json` file in any text editor.\n2. Find the list of files under `delete` parameter.\n3. Remove all these files from your instance.\n\n### 7. Copy new and changed files.\n\nCopy all files from `files` directory (upgrade package) to your the root directory of your instance.\n\n### 8. Run rebuild.\n\n### 9. Copy files from copyAfter\n\n1. Check whether the directory `copyAfter` exists in the package. If it does not exist, then skip this step.\n2. Copy all files\n3. Run rebuild.\n\n### 10. Run after-upgrade script.\n\nCheck whether the file `scripts/AfterUpgrade.php` exists in the package. If it does not exit, then skip this step.\n\nTo the same actions as for *before-upgrade*.\n\n### 11. Change version in the config.\n\n1. Open the file `data/config.php`.\n2. Find the `version` parameter and change its value to the value of the version you upgraded to.\n\nYou can download the fresh instance and compare files using some tool. To make sure files are the same (except *custom* directory and installed extensions).\n\nMake sure that file permissions are correct.\n"
  },
  {
    "path": "docs/administration/upgrading.md",
    "content": "---\nsearch:\n  boost: 3\n---\n\n# How to upgrade EspoCRM\n\n## Upgrade from CLI\n\nThis is the preferable way to upgrade.\n\nCommand to run:\n\n```\nphp command.php upgrade\n```\n\nThis command will check whether the next version is available, download it and install. Once the upgrade is complete, it will prompt to run the command again if a newer version is available.\n\n!!! note\n\n    Upgrading process may take a while. Do not close the terminal until it's finished.\n\n!!! note\n\n    If the next Espo version requires a higher PHP version, upgrade won't be processed, a message will be displayed.\n\nIt's recommended to upgrade whenever the new version is out. If you skip a few minor or major versions before deciding to upgrade, it's more likely that the upgrade will run unsmoothly. For minor or major releases it may be reasonable to wait for a few days before upgrading, as a very fresh release is likely to have yet undiscovered bugs.\n\n!!! warning\n\n    Upgrading between minor or major versions is not always a hands-off process. Incompatibility issues are possible if you have extensions or manual customizations. It is recommended to make a backup before proceeding to upgrade.\n\nVersioning (X.Y.Z):\n\n* X – major – incompatibility issues are very likely, very important to backup before upgrading;\n* Y – minor – incompatibility issues are possible, recommended to backup before upgrading;\n* Z – patch – no-brainer to upgrade.\n\n## Recommendations\n\n1. Make a [backup](backup-and-restore.md) before upgrading.\n2. If the next Espo version requires a higher PHP version, upgrade your PHP (with all extensions). The PHP version you are upgrading to must be supported by your current Espo (usually you make a +2 minor version steps). After that, make sure your Espo is working, cron is running. Make sure that the new PHP version is applied to the CLI (command `php -v`) and to the web server (at Administration > System Requirements > PHP Version).\n3. Make sure you have enough free disk space on the server.\n4. Disable cron before upgrading (at Administration > Settings). Enable it back after upgrade is finished. This will prevent situations when a job started on the previous version and finished on the new version. In most cases this won't cause any issues though. The most significant problem it can cause is the job not being finished.\n5. Enable *Maintenance Mode* before upgrading (at Administration > Settings). Disable after upgrade is finished. This will prevent non-admin users accessing the application before you started upgrading.\n6. *opcache.enable_cli* parameter in PHP should be set to false (usually set to false by default).\n\nIt's recommended to run upgrade either under the webserver user (usually *www-data*) or *root* user.\n\n## Additional parameters\n\nAvailable parameters (only for advanced users):\n\n- `--file=\"EspoCRM-upgrade.zip\"` − install a specific [upgrade package](https://www.espocrm.com/download/upgrades/) (path to file);\n- `-y` − run w/o user confirmation;\n- `-s` − run an upgrade in a single process (dangerous, not recommended to use).\n\nExample of using parameters:\n\n```\nphp command.php upgrade -y --file=\"EspoCRM-upgrade.zip\"\n```\n\n## Upgrade from UI\n\n!!! warning\n\n    This is not a recommended way to upgrade. It may cause problems as the upgrade will be processed in a single web server process.\n\n#### Step 1. Check your current version\n\nTo check your current version, go to Administration > Upgrade page.\n\n#### Step 2. Download needed upgrade packages\n\nGo to the [download upgrade page](https://www.espocrm.com/download/upgrades/) and download needed packages (based on your current version).\n\n#### Step 3. Run upgrade from Administration panel\n\nGo to Administration > Upgrade. Upload and install upgrade packages one by one.\n\n## Breaking changes\n\nEspo upgrades should not break customizations made via the UI. But customizations made via code may break. To review breaking changes before upgrading, check release notes or GitHub issues marked with the *change* tag.\n\n## Quick revert\n\nIf after upgrade the system does not work properly and you want to quickly revert the previous version, you can use this method. Note that this method is not equivalent to a full backup recovery.\n\n1\\. Download the previous version build from the [releases](https://github.com/espocrm/espocrm/releases) on GitHub.\n\n2\\. Remove the following folders in your problem instance:\n\n- `application`\n- `html`\n- `public`\n- `vendor`\n\n3\\. Copy all files from the downloaded build to the root directory of your instance. Existing files to be replaced.\n\n4\\. Fix [file permissions](server-configuration.md#permissions) if needed.\n\n5\\. Run rebuild:\n\n```\nphp rebuild.php\n```\n\n## See also\n\n* [Upgrading manually](upgrading-manually.md)\n* [Troubleshooting](troubleshooting.md)\n\n"
  },
  {
    "path": "docs/administration/users-management.md",
    "content": "# Users management\n\nIn this article:\n\n* [User types](#user-types)\n* [Sending access info](#sending-access-info)\n* [Password recovery](#password-recovery)\n* [User inactivating](#user-inactivating)\n* [Logging in as another user](#logging-in-as-another-user)\n* [Teams](#teams)\n* [See also](#see-also)\n\n## User types\n\nTypes of users:\n\n* Admin\n* Regular\n* Portal\n* API\n* System\n\n### Admin\n\nAn *admin* user has full access to the system. Admin users can create and remove other users, manage access roles, teams, portals, etc.\n\nThere can be multiple admin users in the system. An admin can create another admin users.\n\n### Regular\n\nA regular user has access only to scopes allowed by [Roles](roles-management.md) assigned to the user. A regular users can edit their own user record (if allowed by roles) except the following fields: User Name, Type, Emails, Teams, Roles, Is Active.\n\nAn admin user can manage regular users at Administration > Users.\n\n### Portal\n\nPortal users have access only to the [portal](portal.md) (or multiple portals). A portal user is usually associated with a specific Contact and Account. Access permissions are defined by Portal Roles.\n\nPortal users can be managed at Administration > Portal Users.\n\n### API\n\nAPI users serve for accessing the system via the [API](../development/api.md). Access permissions are defined by [Roles](roles-management.md).\n\nAPI users can be managed at Administration > API Users.\n\n### System\n\nThe system user serves for system purposes. It's not possible to log in under the system user.\n\n## Sending access info\n\nWhen a user (regular, admin or portal) is being created by an admin, it's possible to send an access info email to the user. On the create form, you need to fill in the *Email* field, then the checkbox 'Send access info' will show up. It will initiate the access email sending after user creation. The access info email contains the link to the system and the username.\n\nIf the admin does not specify a **password** for a new user, it will prompt the user to specify their password once they follow the link in the access email. If the password is specified by the admin, it will be sent plain in the email. It's **not recommended** that the password is specified by the admin because of security reasons.\n\nThe email template for access info emails can be changed at Administration > Template Manager > Access info.\n\n## Password recovery\n\nUsers can recover their access if they forgot their password by clicking **Forgot Password?** on the login screen. The user needs to enter their username and email address. If the entered data is correct, an email with a unique link will be sent to the user. This link has an expiration period.\n\nPassword recovery (for all, regular or admin users) can be disabled at Administration > Authentication.\n\nFor security reasons, it's recommended to check **Prevent email address exposure on password recovery form** at Administration > Authentication.\n\nSee the [config parameters](config-params.md#passwords) for password recovery.\n\nThe email template for password recovery can be changed at Administration > Template Manager > Password Change Link.\n\nThe admin can send a password change link for a specific user at the user detail view > the dropdown next to the Edit button > Send Password Change Link.\n\nSee more in the [separate article](passwords.md).\n\n## User inactivating\n\nTo disable access for a specific user w/o deleting the record, the admin needs to uncheck the field *Is Active*.\n\n## Logging in as another user\n\n*As of v7.3.*\n\nThe admin can log in as another regular user. The user detail view > the dropdown next to the *Edit* > Log In.\n\nLimitations:\n\n* WebSocket is disabled when logged in as another user.\n* Requires re-entering admin password to log in as another user.\n* Recommended to open the login link in an incognito/private window to avoid losing a current login session.\n\nThe functionality can be disabled in the config: `'authAnotherUserDisabled' => true`.\n\n## Teams\n\nA user can be related to one or multiple teams. Only the administrator can manage user's teams.\n\nTeams can provide additional access control capabilities. For example, a user added to a specific team, gets the ability to view records related to that team. Or, a user added to a team (e.g. called 'Managers') gets the ability to create and edit records of specific type and full read access.\n\nA user can have the Default Team. All records created by the user will be related to that team by default.\n\n## See also\n\n* [Users quick tour](https://app.supademo.com/demo/cmmbs4x2c18uy22c4j4oiuzll)\n* [Teams quick tour](https://app.supademo.com/demo/cmm0qgpdz1q4p2rl72vtcqtx4)\n"
  },
  {
    "path": "docs/administration/web-to-lead.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Web-to-Lead\n\nIn this article:\n\n* [Lead capture](#lead-capture)\n* [Web form](#web-form)\n* [API request](#api-request)\n* [Lead assignment distribution](#lead-assignment-distribution)\n* [Hooks](#hooks)\n* [Exposing entry point](#exposing-entry-point)\n* [See also](#see-also)\n\n## Lead capture\n\nBy utilizing the Lead Capture feature, an administrator can create entry points for capturing Leads through API and web forms. Follow Administration > Lead Capture to create a Lead Capture record.\n\nParameters:\n\n* Subscribe to Target List – a created lead will be added to a specified target list;\n* Subscribe Contact if exists – if a contact with the same email exists, then the contact will be added to the target list;\n* Target Team – a team created leads will be assigned to;\n* Campaign – statistics will be available in the log of a selected campaign record;\n* Payload Fields – what fields need to be sent in payload (from the web form to the API entry point).\n\n### Double Opt-in (confirmed opt-in)\n\nIf double opt-in is enabled, then your subscribers will need to confirm their intention to opt-in by clicking on a link in an email. The email will be sent automatically once data is received through the API.\n\nCreate an Email Template that will be used for the double opt-in. You can use the following placeholders in a template body:\n\n* `{optInUrl}` – confirmation URL;\n* `{optInLink}` – confirmation link;\n* `{optInDate}` – date when a subscription request was submitted;\n* `{optInTime}` – time when a subscription request was submitted;\n* `{optInDateTime}` – date and time when a subscription request was submitted.\n\nA confirmation link will be added automatically if you haven’t inserted the confirmation link placeholder in the email template.\n\n!!! note\n\n    When sending empty values, use *null* rather than an empty string.\n\n## Web form\n\n*As of v9.0.*\n\nThe Web Form can be enabled for a particular Lead Capture record. A form can be displayed either on a separate page or embedded in an IFRAME. When enabled, a form URL will be displayed in the panel on the right.\n\nParameters:\n\n* Text to display on form\n* Text to display after form submission\n* URL to redirect to after form submission\n* Language used on form\n* Allowed hosts for form embedding (for IFRAME)\n* Use Captcha\n\nCaptcha can be configured under Administration > Integrations. ReCAPTCHA v3 is implemented.\n\nSupported field types:\n\n* Varchar\n* Email\n* Phone\n* Text\n* Person Name\n* Enum\n* Multi-Enum\n* Array\n* Checklist\n* Integer\n* Float\n* Currency\n* Date\n* Date-Time\n* Boolean\n* URL\n* URL-Multiple\n* Address\n\n## API request\n\nYou can use API requests to send Leads directly without using the built-in web-form.\n\nYour web site needs to make a POST request to send form data to your Espo. The request doesn't require any authorization. You just need to use a specific URL with an API Key in it. The information about the request is available in the side panel on the Lead Capture detail view.\n\nRequired headers:\n\n* `Content-Type: application/json`\n* `Accept: application/json`\n\n### PHP\n\nYou can use the [API client](https://github.com/espocrm/php-espo-api-client).\n\n!!! example\n\n    ```php\n    <?php\n\n    use Espo\\ApiClient\\Client;\n\n    $client = new Client($yourEspoUrl);\n    $client->setApiKey($apiKey);\n    $client->setSecretKey($secretKey); // if you use HMAC method\n\n    $apiKey = 'f1b04885f28ee1a6d55dd203daed68f9'; // specify your API key here\n\n    $formData = [\n        'firstName' => $_POST['firstName'] ?: null,\n        'lastName' => $_POST['lastName'] ?: null,\n        'emailAddress' => $_POST['emailAddress'] ?: null,\n    ];\n\n    $client->request(Client::METHOD_POST, 'LeadCapture/' . $apiKey, $formData);\n\n    ```\n\n### Python\n\n[API client in Python](../development/api-client-python.md)\n\n### Directly by a web browser\n\n!!! example\n\n    ```html\n    <div id=\"web-to-lead-form-container\">\n        <form id=\"web-to-lead-form\">\n            <div>\n                <input type=\"text\" name=\"firstName\" placeholder=\"First Name\">\n            </div>\n            <div>\n                <input type=\"text\" name=\"lastName\" placeholder=\"Last Name\" required>\n            </div>\n            <div>\n                <input type=\"email\" name=\"emailAddress\" placeholder=\"Email Address\" required>\n            </div>\n            <div>\n                <button type=\"submit\" name=\"submit\">Submit</button>\n            </div>\n        </form>\n    </div>\n\n    <script type=\"text/javascript\">\n        const webToLeadFormElement = document.getElementById('web-to-lead-form');\n        let webToLeadFormIsSubmitted = false;\n\n        webToLeadFormElement.addEventListener('submit', event => {\n            event.preventDefault();\n\n            if (webToLeadFormIsSubmitted) {\n                return;\n            }\n\n            webToLeadFormIsSubmitted = true;\n            webToLeadFormElement.submit.setAttribute('disabled', 'disabled');\n\n            const payloadData = {\n                firstName: webToLeadFormElement.firstName.value || null,\n                lastName: webToLeadFormElement.lastName.value || null,\n                emailAddress: webToLeadFormElement.emailAddress.value || null,\n            };\n\n            // The URL can be found on the Lead Capture detail view.\n            const url = 'https://URL_OF_YOUR_CRM/api/v1/LeadCapture/API_KEY';\n\n            const xhr = new XMLHttpRequest();\n\n            xhr.open('POST', url, true);\n            xhr.setRequestHeader('Content-Type', 'application/json');\n            xhr.setRequestHeader('Accept', 'application/json');\n\n            xhr.onreadystatechange = () => {\n                if (this.readyState == XMLHttpRequest.DONE && this.status == 200) {\n                    const containerElement = document.getElementById('web-to-lead-form-container');\n\n                    containerElement.innerHTML = 'Sent';\n                }\n            };\n\n            xhr.onerror = () => {\n                webToLeadFormElement.submit.removeAttribute('disabled');\n                webToLeadFormIsSubmitted = false;\n            };\n\n            xhr.send(JSON.stringify(payloadData));\n        });\n    </script>\n    ```\n\nThe `Access-Control-Allow-Origin` header (see [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)) can be set in the `data/config.php` with the parameter `leadCaptureAllowOrigin`. The default value is `*`.\n\n```\n'leadCaptureAllowOrigin' => '*',\n```\n\n## Lead assignment distribution\n\nBy utilizing the [Workflow](workflows.md) or the [BPM](bpm.md) tools, you can create an assignment rule that will distribute leads among team users. *Round-Robin* and *Least-Busy* rules are available.\n\nTo apply the rule only for leads that are coming through the lead capture form, you can use a condition that checks the *Campaign* field (assuming that you have created a separate campaign record for the lead capture form).\n\nYou can also utilize a Formula script (Administration > Entity Manager > Lead > Formula) to set some additional fields.\n\n## Hooks\n\nIt's possible to catch a lead capture event with built-in [hooks](../development/hooks.md#additional-default-hooks). Requires coding.\n\n## Exposing entry point\n\n*As of v9.2.*\n\nIf there's no access to your CRM from the internet, you need to configure your server to handle requests to specific entry points to have the lead capture functioning.\n\nSet the config parameter `leadCaptureSiteUrl` with the base URL that will be exposed.\n\nYou need to handle the following requests:\n\n- GET `{siteUrl}?entryPoint=leadCaptureForm&id={id}`\n- GET `{siteUrl}?entryPoint=confirmOptIn&id={id}`\n- POST `{siteUrl}/api/v1/LeadCapture/{apiKey}`\n- OPTIONS `{siteUrl}/api/v1/LeadCapture/{apiKey}`\n- POST `{siteUrl}/api/v1/LeadCapture/form/{id}`\n\n## See also\n\n* [Quick tour](https://app.supademo.com/demo/cme8qhb2r3w9lh3pyo4d2hh6k)\n* [Drip email campaign with BPM](bpm-drip-email-campaign.md)\n\n\n"
  },
  {
    "path": "docs/administration/webhooks.md",
    "content": "# Webhooks\n\nWebhooks allow other applications to subscribe to specific events happening in EspoCRM and receive data related to those events. Webhooks are supposed to be created via API by other applications. The webhook has a specific *Event* and *URL*. Every time the event occurs, the system will send POST request with some payload to the specified URL.\n\nWebhooks can be created only by API Users (via an API request) and Administrators. An API User has to have *Webhooks* scope enabled in Roles. An API User has also to have access to all entity types for which webhooks are intended to be created.\n\n* [Subscription](#subscription)\n* [Events](#events)\n* [Webhook requests](#webhook-requests)\n* [Error handling](#error-handling)\n* [Signature checking](#signature-checking)\n* [Config parameters](#config-parameters)\n* [Local host URLs](#local-host-urls)\n* [Debugging](#debugging)\n\n## Subscription\n\n### Creating request\n\n`POST api/v1/Webhook`\n\n```json\n{\n    \"event\": \"EVENT\",\n    \"url\": \"URL\"\n}\n```\n\nParameters:\n\n* `URL` – string – an endpoint;\n* `skipOwn` – boolean – to skip if the event was initiated by the user owning the webhook (as of v9.2).\n\nA Webhook ID and a secret key will be sent back in the response:\n\n* `id` – an ID of created webhook,\n* `secretKey` – a generated secret key,\n\n\n### Deleting request\n\n`DELETE api/v1/Webhook/WEBHOOK_ID`\n\n### Administration\n\nAn administrator can manage webhooks at Administration > Webhooks. It's possible to remove, edit or create webhooks there.\n\n## Events\n\n!!! note\n\n    The list of available entity types can be obtained at Administration > Entity Manager.\n\n### ENTITY_TYPE.create\n\nTriggered when a record is created. All record attributes will be sent in a payload.\n\nExample: `Account.create`\n\n### ENTITY_TYPE.update\n\nTriggered when a record is updated. Only updated record attributes will be sent in a payload.\n\nExample: `Account.update`\n\n### ENTITY_TYPE.delete\n\nTriggered when a record is removed.\n\nExample: `Account.delete`\n\n### ENTITY_TYPE.fieldUpdate.FIELD\n\nTriggered when a specific field is updated. New field attributes will be sent in a payload.\n\nExample: `Account.fieldUpdate.assignedUserId`\n\n!!! note\n\n    The list of available fields can be obtained at Administration > Entity Manager > fields.\n\n\n## Webhook requests\n\nEvery webhook request (sent by EspoCRM to a specified URL) is of POST type. A content type is *application/json*.\n\nEvents related to the same hook are sent in batches. The request payload is always an array (even if only one record is sent).\n\nOne event occurred:\n\n```json\n[\n    {\n        \"id\": \"someId\",\n        \"name\": \"some name\"\n    }\n]\n```\n\nMultiple events occurred:\n\n```json\n[\n    {\n        \"id\": \"someId1\",\n        \"name\": \"some name 1\"\n    },\n    {\n        \"id\": \"someId2\",\n        \"name\": \"some name 2\"\n    }\n]\n```\n\nRequest sending is processed by the scheduled job *Process Webhook Queue* (Administration > Scheduled Jobs). By default, it runs every 5 minutes. You can change the scheduling.\n\n## Error handling\n\nWhen EspoCRM is trying to send a webhook request and an error occurs, EspoCRM will process it the following ways:\n\n* errors 400, 401, 403, 404, 405, 408, connection timed out, or connection failed - will try to make another attempt;\n* error 410 - hook will be removed immediately.\n\n## Signature checking\n\nIt's possible to check the authenticity of a webhook request by comparing the signature passed in the *Signature* header with a value calculated on the server that receives the request.\n\nExample for PHP:\n\n```php\n$signature = base64_encode($webhookId . ':' . hash_hmac('sha256', $payload, $secretKey));\n```\n\n* *webhookId* can be obtained from the response upon webhook creation or at Administration > Webhooks;\n* *secretKey* can be obtained from the response upon webhook creation or at Administration > Webhooks;\n* *payload* is a payload of the request.\n\n!!! important\n\n    Prior to v9.0, the signature was passed in the *X-Signature* header and constructed in a slightly different manner. *X-Signature* will still be passed after v9.0 and will be available until v11.0. If your script checks *X-Signature*, you need to fix it to *Signature*.\n\n\n## Config parameters\n\nCan be set manually in `data/config.php`.\n\n* *webhookMaxCountPerUser* = 50\n* *webhookQueueEventPortionSize* = 20\n* *webhookQueuePortionSize* = 20\n* *webhookBatchSize* = 50\n* *webhookMaxAttemptNumber* = 4\n* *webhookFailAttemptPeriod* = '10 minutes'\n* *webhookConnectTimeout* = 5 (seconds)\n* *webhookTimeout* = 10 (seconds)\n* *webhookAllowedAddressList*\n\n## Local host URLs\n\n*As of v9.3.2*\n\nBy default, internal URLs (like *http://localhost*) are forbidden. To allow, you need to define the needed address in the *webhookAllowedAddressList* config parameter, in the following format *host:port*.\n\n```\n'webhookAllowedAddressList' => ['localhost:80'],\n```\n\n## Debugging\n\nQueues are stored in two database tables: `webhook_queue_item` and `webhook_event_queue_item`. Webhook Queue Items are available from the UI at Administration > Webhooks > menu in the top-right corner > Webhook Queue Items.\n\nYou can enable [debug mode](troubleshooting.md#debug-mode) to see more details in the log.\n"
  },
  {
    "path": "docs/administration/websocket.md",
    "content": "# WebSocket\n\nThe WebSocket enables interaction between a server and a client (browser) without the latter making polling requests. Example: When a new notification is received, the server sends the information to the browser in real time.\n\nOut-of-the-box the WebSocket covers the following features:\n\n* New in-app notifications;\n* New event reminders;\n* Updates in stream on the record detail view;\n* Updates of the detail view.\n\n!!! important\n\n    You need to have *zmq* php extension installed.\n\nEnable **Use WebSocket** parameter at Administration > Settings.\n\n## Daemon\n\nYou need to run `websocket.php` as a daemon.\n\n### Using systemd\n\nCreate a file `/etc/systemd/system/espocrm-websocket.service`.\n\n```\n[Unit]\nDescription=EspoCRM WebSocket Service\nRequires=mysql.service\nAfter=mysql.service\nStartLimitIntervalSec=0\n\n[Service]\nType=simple\nRestart=always\nRestartSec=5\nUser=www-data\nExecStart=/usr/bin/php /path/to/espocrm/websocket.php\nStandardError=/path/to/espocrm/data/logs/websocket.log\n\n[Install]\nWantedBy=default.target\n```\n\nCommand to get the service to start on boot:\n\n`systemctl enable espocrm-websocket.service`\n\n\nCommand to start the service:\n\n`systemctl start espocrm-websocket.service`\n\n## SSL support\n\nYou need to set up a proxy that will forward SSL requests to our websocket server and vice-versa.\n\n### Apache\n\nYou need to have *proxy* and *proxy_wstunnel* modules installed.\n\n```\nsudo a2enmod proxy\nsudo a2enmod proxy_wstunnel\n```\n\nIn your Apache config inside the *VirtualHost* section for SSL (`<VirtualHost _default_:443>`), add the following:\n\n```\n<IfModule proxy_module>\n  ProxyRequests Off\n  <Location /wss>\n       ProxyPass ws://your-domain:8080\n       ProxyPassReverse ws://your-domain:8080\n  </Location>\n</IfModule>\n```\n\n### Nginx\n\nAdd to *server.conf*:\n\n```\nmap $http_upgrade $connection_upgrade {\n  default upgrade;\n  '' close;\n}\n\nupstream websocket {\n  server 127.0.0.1:8080;\n}\n```\n\nAdd to the section `server`:\n\n```\nlocation /wss {\n    proxy_pass http://websocket;\n    proxy_http_version 1.1;\n    proxy_set_header Upgrade $http_upgrade;\n    proxy_set_header Connection $connection_upgrade;\n    proxy_read_timeout 12h;\n}\n```\n\n!!! note\n\n    By default, Nginx has *proxy_read_timeout* parameter set to 60 (seconds). You need to increase the value to avoid the connection being terminated too soon. In the example, we set it to 12h.\n\n## Checking whether it works\n\nClick F12 to open the browser console. See whether there's any error related to the WebSocket. If you enabled the WebSocket in the settings, the frontend client will try to connect to the WebSocket once the page is loaded. If something went wrong, an error will be displayed in the browser console.\n\n## Config params\n\n* webSocketDebugMode – bool – `false` – if you run a server (`php websocket.php`) manually from CLI, you will be able to see debug messages in the terminal; changing requires WebSocket process restart;\n* webSocketUrl – string – a custom URL for websocket; used only by the client (frontend);\n* webSocketUseSecureServer – bool – `false` – to use SSL w/o a proxy;\n* webSocketZeroMQSubscriberDsn – string – `tcp://127.0.0.1:5555` – an endpoint to bind to for message listening; to be changed when used inside a container;\n* webSocketZeroMQSubmissionDsn – string – `tcp://localhost:5555'` – an endpoint to connect to for message sending; to be changed when used inside a container;\n* webSocketPort – string – by default '8443' (ssl) or '8080';\n* webSocketSslCertificateFile\n* webSocketSslCertificateLocalPrivateKey\n* webSocketSslCertificatePassphrase\n* webSocketSslAllowSelfSigned\n* webSocketUseSecureServer\n\n## Installing ZMQ\n\n### Option 1\n\n```\nsudo apt install php-zmq\n```\n\n### Option 2\n\nIf the previous won't work, try compiling.\n\nYou need to have `libzmq3-dev` installed:\n\n```\napt install libzmq3-dev\n```\n\nYou need to have `php-dev` installed:\n\n```\napt install php-dev\n```\n\nThen execute the following commands (from the *root* user):\n\n```\ncd /usr\ncurl -fSL https://github.com/zeromq/php-zmq/archive/e0db82c3286da81fa8945894dd10125a528299e4.tar.gz -o php-zmq.tar.gz\ntar -zxf php-zmq.tar.gz\ncd php-zmq-e0db82c3286da81fa8945894dd10125a528299e4\nphpize && ./configure\nmake\nmake install\ncd .. && rm -rf php-zmq-e0db82c3286da81fa8945894dd10125a528299e4 && rm php-zmq.tar.gz\n```\n\nThen edit *php.ini* (both for the CLI and webserver), add:\n\n```\nextension=zmq\n```\n\n## Event loop implementations\n\nThe default [event loop](https://github.com/reactphp/event-loop?tab=readme-ov-file#loop-implementations) implementation of the WebSocket server relies on file descriptors. By default, the maximum number of file descriptors per process may be set relatively low (commonly 1024).\n\nFor production, it's reasonable to install [ext-ev](https://pecl.php.net/package/ev) extension, or any other recommended by ReactPHP. With the extension installed, it will automatically choose the appropriate event loop implementation.\n"
  },
  {
    "path": "docs/administration/workflows-telegram-message.md",
    "content": "# Sending telegram message with Workflow\n\nSince Advanced Pack version 2.4.0 it’s possible to send HTTP requests with Workflows and BPM tools.\n\n* [Workflow configuration](#workflow-configuration)\n* [Telegram configuration](#telegram-configuration)\n\n\n### Workflow configuration\n\nCreate a workflow rule. Specify needed conditions and then add action Send HTTP Request.\n\nSet:\n\n**Request Type:** POST\n\n**Content-type:** None\n\n**URL:** `https://api.telegram.org/bot<TELEGRAM_BOT_AUTH_TOKEN>/sendMessage`\n\nExample: `https://api.telegram.org/bot3457233623:AAGKRIhcGSJ7bKFFh6DJMRWhyRbVBSRS53c/sendMessage`\n\n**Payload:**\n\n```\n{\n    \"chat_id\": \"CHAT_ID\",\n    \"text\": \"Created new Contact:\\n {$name}/n *Phone number:* {$phoneNumber}\",\n    \"parse_mode\": \"Markdown\"\n}\n```\n\n* chat_id supports 2 formats:\n\t- -1003332162016\n\t- @chat-name\n* text supports:\n\t- plain text.\n\t- Target Entity variables (e.g. {$description}, {$name}, {$phoneNumber}, etc.).\n\t- Markdown text. \n* \"parse_mode\" is optional parameter. Can send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.\n\nYou can read more about bot request methods and payloads [here](https://core.telegram.org/bots/api).\n\n### Telegram configuration\n\n1. Create a new Telegram channel.\n2. Create a new [Telegram bot](https://core.telegram.org/bots#3-how-do-i-create-a-bot).\n3. Add the bot to your Telegram channel.\n4. Add the bot to the channel admins group."
  },
  {
    "path": "docs/administration/workflows.md",
    "content": "---\nsearch:\n  boost: 2\ntags:\n  - automation\n---\n\n# Workflows\n\nThe Workflows tool is available in [Advanced Pack](https://www.espocrm.com/extensions/advanced-pack/).\n\nThe Workflows tool automates your business processes in an easy way. Possible use cases of what can be achieved:\n\n* Automatically modify records when specific conditions are met. \n* Define assignment rules for efficient task distribution.\n* Add buttons on the record detail view to trigger business logic actions.\n* Integrate Espo with external systems through an API for data exchange.\n* And many more.\n\nYou can access Workflows from the Administration panel. Only administrators can view or configure workflows.\n\nWhen creating a Workflow rule, you need to set:\n\n* Target entity type – the entity type the rule is applied to;\n* Trigger type – how the rule will be triggered;\n* Conditions – conditions need to be met to trigger the rule;\n* Actions – what actions to perform when the rule is triggered.\n\nIn this article:\n\n* [Trigger types](#trigger-types)\n* [Conditions](#conditions)\n* [Actions](#actions)\n* [Using formula in actions](#using-formula-in-actions)\n* [Formula functions](#formula-functions)\n* [Config parameters](#config-parameters)\n* [See also](#see-also)\n\n## Trigger types\n\n* [After record created](#after-record-created)\n* [After record updated](#after-record-updated)\n* [After record create or updated](#after-record-created-or-updated)\n* [Manual](#manual)\n* [Scheduled](#scheduled)\n* [Sequential](#sequential)\n* [Signal](#signal)\n\n### After record created\n\nTriggered only when a new record is created. If specified conditions are met, then actions will be executed.\n\n### After record updated\n\nTriggered only when an existing record is updated. If specified conditions are met, then actions will be executed.\n\n!!! important\n\n    Be aware of potential loops. A built-in safeguard prevents looping in basic cases. However, loops can still occur – for example, when using a formula to update records.\n\n### After record created or updated\n\nTriggered when a new record is created or an existing record is updated. If specified conditions are met, then actions will be executed.\n\nFor Workflow rules with this trigger type, it's a common practice to have a condition that checks whether some field was changed. For example, if a Case's status is changed, then do some actions.\n\n### Manual\n\n*As of v2.12.*\n\nTriggered manually by a user by clicking a button (or a dropdown menu item) on the record detail view.\n\nThe ability to define:\n\n* an element type (a button or a dropdown item);\n* a label text;\n* teams allowed to run the Workflow;\n* dynamic-logic conditions that make a button/menu-item available;\n* access to the record required to be able to run the Workflow (read, edit, admin).\n\nLimitations:\n\n* Portal Users are not allowed to run *Manual* Workflows.\n\nTo show a custom result message use the function [workflow\\alert](workflows.md#workflowalert) in an Execute Formula Script action.\n\n### Scheduled\n\nTriggered according to a defined scheduling. You can set up it to run every day, every week, etc. Actions will be applied for records returned by a specified *List* Report. Hence, you need also to create a *List* Report.\n\nScheduling is specified in a crontab notation.\n\n```\n* * * * * *\n| | | | | |\n| | | | | +-- Year              (range: 1900-3000)\n| | | | +---- Day of the Week   (range: 1-7, 1 standing for Monday)\n| | | +------ Month of the Year (range: 1-12)\n| | +-------- Day of the Month  (range: 1-31)\n| +---------- Hour              (range: 0-23)\n+------------ Minute            (range: 0-59)\n```\n\nHow it works:\n\n1. You need to create a *List* Report showing records that met specific criteria. You can specify any columns for the Report, it doesn't matter in this context.\n2. Then, create a Workflow rule with the *Scheduled* trigger type, select the Report you created before. Specify the needed scheduling.\n3. Specify one or multiple actions in the Workflow rule.\n\nThe Workflow rule will be running in idle according to the specified scheduling. On each run, it will run the Report and obtain all records from the Report result. Then, it will apply the action (or multiple actions) for every record.\n\n!!! example \"Example, a use case\"\n\n    Send a notification email to customers who have their license expiring in 1 week. You will need a report listing contacts who have their license expiring exactly in 7 days. Set up a Workflow to run once a day.\n\n### Sequential\n\nIs supposed to be run by another Workflow. Provides the ability to create complex logic.\n\n1. Create a Workflow rule with the *Sequential* trigger type.\n2. Create another Workflow rule with another trigger type. Add an action *Trigger another Workflow* and select the Workflow rule from the step 1.\n\n!!! note\n\n    It can be reasonable to utilize [BPM tool](bpm.md) rather than Workflows if you need more complex logic.\n\n### Signal\n\nTriggered when a specified signal is broadcast in the system. Only object signals can be used here. See [more info](bpm-signals.md) about signals.\n\n----\n\n## Conditions\n\nYou can specify conditions that must be met to trigger a Workflow rule. There are two ways how conditions can be specified: with the UI condition builder and with a Formula script.\n\nIn formula, it's possible to have multiple expressions separated by a semicolon. The evaluation of the last expression will be returned as the result.\n\n### UI condition builder\n\nSome available condition types:\n\n* _equals_ – the field equals to a specific value or a value of another field;\n* _was equal_ – the field was equal to a specific value before the Workflow was triggered;\n* _not equals_ – the field does not equal to a specific value or a value of another field;\n* _was not equal_ – the field was not equal to specific value before the Workflow was triggered;\n* _empty_ – the field value is empty;\n* _not empty_ – the field value is not empty;\n* _changed_ – the field was changed;\n* _not changed_ – the field was not changed.\n\n### Formula conditions\n\nFormula provides the ability to define conditions of any complexity. To read about formula syntax, follow [this article](formula.md).\n\n!!! note\n\n    There should not be any `;` delimiter used in formula code when it determines a condition. It should be one expression that returns a value (TRUE or FALSE).\n\n!!! example\n\n    Expression with the logical AND:\n\n    ```\n    status == 'New' && assignedUserId == null\n    ```\n\n----\n\n## Actions\n\n* [Send Email](#send-email)\n* [Create Record](#create-record)\n* [Create Related Record](#create-related-record)\n* [Update Target Record](#update-target-record)\n* [Update Related Record](#update-related-record)\n* [Link with another Record](#link-with-another-record)\n* [Unlink from another Record](#unlink-from-another-record)\n* [Apply Assignment Rule](#apply-assignment-rule)\n* [Create Notification](#create-notification)\n* [Make Followed](#make-followed)\n* [Trigger another Workflow](#trigger-another-workflow)\n* [Run Service Action](#run-service-action)\n* [Start BPM Process](#start-bpm-process)\n* [Send HTTP Request](#send-http-request)\n* [Execute Formula Script](#execute-formula-script)\n\n### Send Email\n\nSystem will send an email using a specified Email Template. A recipient’s email address can be taken from the target record, any related record, the current user, followers, team users or specified explicitly. The email can be sent immediately or delayed for a specific interval.\n\nIf you specify the *From* address with an address of an existing Group Email Account, then SMTP parameters of that account will be used for sending.\n\nIt's possible to add an **opt-out** link to an email body.\n\nIt's possible to specify multiple email addresses by separating them with a semicolon.\n\nIt's possible to use a formula variable when specifying an email address. Example: `{$$variable}`. As of v3.6.\n\nAdditional attachments can be added to an email using the *Attachments Variable* parameter. Specify a Formula variable name that contains an attachment ID or an array of attachment IDs. You can generate needed attachments in a Formula script in a previous action. As of v3.6.\n\n### Create Record\n\nThe system will create a new record of any entity type. If there is a relationship between the target entity type and the entity type of records being created, it's possible to relate them.\n\nThere is the ability to define a Formula script to calculate field values.\n\n!!! note\n\n    Variables defined within the Formula script won't be available in following actions (or the BPM process). They are only available within the current script.\n\n### Create Related Record\n\nThe system will create the record related to a target record.\n\nIt's possible to define a Formula script to calculate field values. Note: Variables defined within the Formula script will be only available within the current script.\n\n### Update Target Record\n\nAllows to change specific fields of a target record.\n\nIt's possible to define a Formula script to calculate field values. Note: Variables defined within the Formula script will be only available within the current script.\n\n!!! note\n\n    It's not recommended to rely on an *Update Target Record* action triggering another after-update Workflow. In some cases it won't work. It's better to define additional actions in the same Workflow or trigger a *Sequential* Workflow.\n\n!!! warning \"Important\"\n\n    Formula within an *Update Target Record* action must be utilized only for field updating. Use the *Execute Formula Script* action for any other need.\n\nFor Link-Multiple, Array, Multi-Enum, and Checklist fields it's possible to add or remove items without loosing set items. For example, adding a specific Team while preserving existing Teams.\n\nThere is the ability to **delete** the record with the following formula code: `deleted = true`;\n\n### Update Related Record\n\nAllows to change specific fields of a related record (or records). \n\nIt's possible to define Formula script to calculate field values. Note: Variables defined within formula won't be passed back.\n\nThere is the ability to delete the record with the following formula code: `deleted = true`;\n\n!!! tip\n\n    If there can be many related records, it's reasonable to process updating these records in idle. For this, utilize the *Trigger Another Workflow* action with a small or zero delay. Define an *Update Related Record* action in a *Sequential* Workflow rule.\n\n### Link with another Record\n\nRelates the target record with another specific record. For example, add specific team to the record.\n\n### Unlink from another Record\n\nUnrelates the target record from another specific record. For example, remove a specific team from the record.\n\n### Apply Assignment Rule\n\nAssigns the target record to a User using a specific distribution rule. There are two available rules: *Round-Robin* and *Least-Busy*.\n\n* Round-Robin – Users are chosen from the top to the bottom of a list and then starting again.\n* Least-Busy – the User who has fewer assigned records will be chosen for assignment.\n\n*List Report* – determines what records will be taken into account to calculate the number of assigned records for *Least-Busy* distribution. For example, we need to take into account only active Cases.\n\n*Target Team* – Users of the selected team will take part in the assignment process.\n\n*Target User Position* – Allows to restrict the list of users that will take part in the assignment process. Users that have the selected position (in team) will take part. If the field is set to *All*, then all team members will take part.\n\n### Create Notification\n\nNotify specific users with a message.\n\nIt's possible to use placeholders in the message template:\n\n* `{entity}` – a target record;\n* `{user}` – a current user.\n\n### Make Followed\n\nForces specific users to follow the target record or a specified related record.\n\n### Trigger another Workflow\n\nAllows to make *Sequential* Workflows. It's possible to diverge Workflows by condition: you can set up a Workflow to trigger two Workflows with different conditions defined in those Workflows.\n\nIt's possible to delay executing of a *Sequential* Workflow. In a *Sequential* Workflow, you can define the condition that checks whether specific fields were changed since the parent Workflow was triggered by using _Changed_ and _Was Equal_ condition types.\n\nA *Target* for a triggered Workflow can be substituted with a related record.\n\n!!! note\n\n    For complex logic, it can be more reasonable to utilize [BPM tool](bpm.md) rather than Workflows.\n\n!!! note\n\n    It's possible to trigger only Workflow rules of *Sequential* type.\n\n### Run Service Action\n\nAllows to run specific service scripts.\n\nThe following actions are available out-of-the-box:\n\nMeetings/Calls:\n\n* *Send Invitations* – sends invitations to event attendees\n\nQuotes/Sales Orders/Invoices:\n\n* *Add Items*\n* *Convert Currency* – converts all currency values based on current rates (since version 5.7.0)\n* *Send in Email*\n\nOpportunities:\n\n* *Convert Currency*\n\nContacts/Leads/Accounts:\n\n* *Opt-out* – unsubscribes from a specific target list or entirely\n\nUsers:\n\n* *Generate Password* – generates a new password for a user and sends it to their email address\n\nDevelopers can write their own service actions. See [more detail](../development/workflow-service-actions.md).\n\n### Start BPM Process\n\nStarts a BPM process. You can specify what target record will be used for the process.\n\n### Send HTTP Request\n\nProvides the ability to call an external API. Can be utilized to integrate Espo with other systems.\n\nSupported request methods:\n\n* GET\n* POST\n* PUT\n* PATCH\n* DELETE\n\nAdditional headers can be specified.\n\nPlaceholders can be used in:\n\n* Headers\n* Request URL\n* Payload JSON\n\nAvailable placeholders:\n\n* *{$attribute}* – a value of an [attribute](terms-and-naming.md#attribute) of a target record;\n* *{$$variable}* – a value of a formula variable;\n* *{#secrets.name}* – an App Secret; available only in headers; as of v3.4.7.\n\n#### Payload\n\nA payload can be specified in a JSON format or taken from a formula variable.\n\nWhen specified in JSON, it's possible to use placeholders.\n\nExample of payload with placeholders:\n\n```\n{\n    \"espoRecordId\": \"{$id}\",\n    \"name\": \"{$name}\",\n    \"userId\": \"{$assignedUserId}\",  \n    \"intValue\": {$$myIntegerVariable},\n    \"boolValue\": {$$myBooleanVariable},\n    \"stringValue\": \"{$$myStringVariable}\"\n}\n```\n\nAlternatively, you can craft a payload in formula script, store it in a variable and then use this variable as a payload. The variable value can be an object, array, string or a scalar.\n\n#### Handling HTTP response\n\nA response body of an HTTP request will be available in formula with the function `workflow\\lastHttpResponseBody()`. It can be accessed in the following workflow actions within the workflow rule. For example, in an Execute Formula Script action.\n\nJSON attributes can be retrieved with the function `json\\retrieve`.\n\n!!! example\n\n    A POST request returns a JSON body `{\"id\": \"SOME_ID\"}`. We need to store that ID. Add a *Update Target Record* action in the same Workflow rule with the formula script:\n\n    ```\n    $id = json\\retrieve(workflow\\lastHttpResponseBody(), 'id');\n    entity\\setAttribute('someIdField', $id);\n    ```\n\n!!! note\n\n    In the context of a BPM process, the last response body is available only within the Task that contains the Send HTTP Request action. The response won't be passed further along the process flow. But if you assign the response value to a variable, the variable will be passed further.\n\nIn the context of a BPM process, it's possible to catch response errors with an Error Boundary Event. The error code can be obtained by using `bpm\\caughtErrorCode` function.\n\n#### Localhost\n\nBy default, the system does not allow internal URLs, including localhost. To enable it, you need to define in the config:\n\n```php\n'workflowSendRequestAllowedAddressList' => ['localhost:80', 'localhost:443'],\n```\n\n### Execute Formula Script\n\nExecutes a [formula](formula.md) script.\n\nVariables defined within the script will be passed back. They will be available in the following Workflow actions within the rule. When used in a BPM process, the defined variables will be available further in the flow.\n\n## Using formula in actions\n\nIt's possible to define formula to calculate fields in the following actions:\n\n* Execute Formula Script,\n* Create Record,\n* Update Target Record,\n* Create Related Record,\n* Update Related Record.\n\n## Formula functions\n\n#### workflow\\targetEntity\\attribute\n\n`workflow\\targetEntity\\attribute(ATTRIBUTE_NAME)`\n\nReturns an attribute value of the target entity. Useful when the scope is switched to a related record.\n\n#### workflow\\targetEntity\\attributeFetched\n\n`workflow\\targetEntity\\attributeFetched(ATTRIBUTE_NAME)`\n\nReturns a previous attribute value of the target entity (before the Workflow was triggered).\n\n#### workflow\\trigger\n\n`workflow\\trigger(ENTITY_TYPE, ID, WORKFLOW_ID)`\n\nTriggers another Workflow rule.\n\n#### workflow\\signalParam\n\n`workflow\\signalParam(PARAM)`\n\nGet a signal param.\n\n#### workflow\\lastCreatedEntityId\n\n`workflow\\lastCreatedEntityId()`\n\n*As of v3.9.*\n\nReturns the ID of the last record that has been created within the workflow rule by a *Create Record* or *Created Related Record* action. Available only within a workflow rule and within a BPM's Task activity.\n\n#### workflow\\alert\n\n`workflow\\alert(MESSAGE, [AUTO_CLOSE], [TYPE])`\n\n*As of v3.9.*\n\nSets an alert message to show for the user after a manual workflow in run. AUTO_CLOSE is boolean. TYPE can be `\"warning\"`, `\"danger\"`, `\"success\"`, `\"info\"`.\n\nMarkdown is supported. It enables the ability to display a link for the user.\n\n!!! note\n\n    The alert function only works in the context of the manual workflow. It won't work if called from a BPM processes started by the manual workflow. It won't work if called from another workflow initiated by the manual workflow.\n\n## Config parameters\n\n* `workflowSendRequestTimeout` – `7` – a timeout for the Send HTTP Request action;\n* `workflowEmailSiteUrl` – to override the default site URL (can be helpful if there's no access to your CRM from the internet, but you need to handle opting out & tracking URLs; you will need to configure your server to handle requests to the specified URL); the parameter is applied for emails sent using workflows and BPM;\n* `workflowSendRequestAllowedAddressList` – a white list of internal URLs which are allowed in the Send HTTP Request action; example: `['localhost:80']`; required if you want to call localhost endpoints; applier for both workflows and BPM.\n\n## See also\n\n* [Quick tour](https://app.supademo.com/demo/cmf4988mv261h39ozgxi1un4e)\n* [Birthday notifications in EspoCRM](https://www.espocrm.com/blog/birthday-notifications-in-espocrm/)\n* [Adding custom service action for Workflows](../development/workflow-service-actions.md)\n* [Automated Email-to-Lead with Workflows](https://www.espocrm.com/blog/automated-email-to-lead-with-workflows/)\n* [Automatic posting to stream with Workflows](https://www.espocrm.com/blog/automatic-posting-to-stream-with-workflow/)\n* [Sending Telegram message with Workflows](workflows-telegram-message.md)\n"
  },
  {
    "path": "docs/api/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n    <title>EspoCRM API Docs</title>  \n    <script src=\"https://unpkg.com/@stoplight/elements/web-components.min.js\"></script>\n    <link rel=\"stylesheet\" href=\"https://unpkg.com/@stoplight/elements/styles.min.css\">\n  </head>\n  <body>\n    <elements-api\n      apiDescriptionUrl=\"spec.json\"\n      layout=\"responsive\"\n      router=\"hash\"\n      hideTryIt=\"true\"\n    />\n  </body>\n</html>\n\n"
  },
  {
    "path": "docs/api/spec.json",
    "content": "{\n    \"openapi\": \"3.1.1\",\n    \"info\": {\n        \"title\": \"EspoCRM API\",\n        \"version\": \"1.0.0\"\n    },\n    \"paths\": {\n        \"\\/Account\": {\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Account_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Account\",\n                \"description\": \"Create a new 'Account' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"customers\",\n                                \"resellers\",\n                                \"partners\",\n                                \"recentlyCreated\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"website\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"type\",\n                                    \"industry\",\n                                    \"sicCode\",\n                                    \"contactRole\",\n                                    \"contactIsInactive\",\n                                    \"billingAddressStreet\",\n                                    \"billingAddressCity\",\n                                    \"billingAddressState\",\n                                    \"billingAddressCountry\",\n                                    \"billingAddressPostalCode\",\n                                    \"shippingAddressStreet\",\n                                    \"shippingAddressCity\",\n                                    \"shippingAddressState\",\n                                    \"shippingAddressCountry\",\n                                    \"shippingAddressPostalCode\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"billingAddressMap\",\n                                    \"shippingAddressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account\",\n                \"description\": \"List Account records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"summary\": \"Read Account\",\n                \"description\": \"Read an existing 'Account' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Version-Number\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A version number for optimistic concurrency control. Obtained from the 'versionNumber' field.\"\n                    }\n                ],\n                \"summary\": \"Update Account\",\n                \"description\": \"Update an existing 'Account' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"summary\": \"Remove Account\",\n                \"description\": \"Remove an existing 'Account' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/calls\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateEnd\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"direction\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"phoneNumbersMap\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . calls\",\n                \"description\": \"List 'Call' records related through the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . calls\",\n                \"description\": \"Relate 'Call' record though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . calls\",\n                \"description\": \"Unrelate 'Call' record related though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/callsPrimary\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateEnd\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"direction\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"phoneNumbersMap\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . callsPrimary\",\n                \"description\": \"List 'Call' records related through the 'callsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . callsPrimary\",\n                \"description\": \"Relate 'Call' record though the 'callsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . callsPrimary\",\n                \"description\": \"Unrelate 'Call' record related though the 'callsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/cases\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"closed\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"number\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"type\",\n                                    \"description\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"leadId\",\n                                    \"leadName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"contactsIds\",\n                                    \"contactsNames\",\n                                    \"inboundEmailId\",\n                                    \"inboundEmailName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"isInternal\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . cases\",\n                \"description\": \"List 'Case' records related through the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . cases\",\n                \"description\": \"Relate 'Case' record though the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . cases\",\n                \"description\": \"Unrelate 'Case' record related though the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/contacts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . contacts\",\n                \"description\": \"List 'Contact' records related through the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . contacts\",\n                \"description\": \"Relate 'Contact' record though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . contacts\",\n                \"description\": \"Unrelate 'Contact' record related though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/contactsPrimary\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . contactsPrimary\",\n                \"description\": \"List 'Contact' records related through the 'contactsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . contactsPrimary\",\n                \"description\": \"Relate 'Contact' record though the 'contactsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . contactsPrimary\",\n                \"description\": \"Unrelate 'Contact' record related though the 'contactsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/documents\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"draft\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"fileId\",\n                                    \"fileName\",\n                                    \"status\",\n                                    \"type\",\n                                    \"publishDate\",\n                                    \"expirationDate\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"folderId\",\n                                    \"folderName\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . documents\",\n                \"description\": \"List 'Document' records related through the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Document\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Document record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . documents\",\n                \"description\": \"Relate 'Document' record though the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Document record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . documents\",\n                \"description\": \"Unrelate 'Document' record related though the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/emails\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"subject\",\n                                    \"fromName\",\n                                    \"fromAddress\",\n                                    \"fromString\",\n                                    \"replyToString\",\n                                    \"replyToName\",\n                                    \"replyToAddress\",\n                                    \"addressNameMap\",\n                                    \"from\",\n                                    \"to\",\n                                    \"cc\",\n                                    \"bcc\",\n                                    \"replyTo\",\n                                    \"personStringData\",\n                                    \"isRead\",\n                                    \"isNotRead\",\n                                    \"isReplied\",\n                                    \"isNotReplied\",\n                                    \"isImportant\",\n                                    \"inTrash\",\n                                    \"inArchive\",\n                                    \"folderId\",\n                                    \"isUsers\",\n                                    \"isUsersSent\",\n                                    \"folderName\",\n                                    \"folderStringId\",\n                                    \"folderStringName\",\n                                    \"nameHash\",\n                                    \"typeHash\",\n                                    \"idHash\",\n                                    \"messageId\",\n                                    \"messageIdInternal\",\n                                    \"emailAddress\",\n                                    \"fromEmailAddressId\",\n                                    \"fromEmailAddressName\",\n                                    \"toEmailAddressesIds\",\n                                    \"toEmailAddressesNames\",\n                                    \"ccEmailAddressesIds\",\n                                    \"ccEmailAddressesNames\",\n                                    \"bccEmailAddressesIds\",\n                                    \"bccEmailAddressesNames\",\n                                    \"replyToEmailAddressesIds\",\n                                    \"replyToEmailAddressesNames\",\n                                    \"bodyPlain\",\n                                    \"body\",\n                                    \"isHtml\",\n                                    \"status\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"hasAttachment\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"dateSent\",\n                                    \"deliveryDate\",\n                                    \"sendAt\",\n                                    \"isAutoReply\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"sentById\",\n                                    \"sentByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"repliedId\",\n                                    \"repliedName\",\n                                    \"repliesIds\",\n                                    \"repliesNames\",\n                                    \"isSystem\",\n                                    \"isJustSent\",\n                                    \"isBeingImported\",\n                                    \"skipNotificationMap\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"assignedUsersIds\",\n                                    \"assignedUsersNames\",\n                                    \"inboundEmailsIds\",\n                                    \"inboundEmailsNames\",\n                                    \"emailAccountsIds\",\n                                    \"emailAccountsNames\",\n                                    \"icsContents\",\n                                    \"icsEventData\",\n                                    \"icsEventUid\",\n                                    \"icsEventDateStart\",\n                                    \"icsEventDateStartDate\",\n                                    \"createEvent\",\n                                    \"createdEventId\",\n                                    \"createdEventType\",\n                                    \"createdEventName\",\n                                    \"groupFolderId\",\n                                    \"groupFolderName\",\n                                    \"groupStatusFolder\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"tasksIds\",\n                                    \"tasksNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . emails\",\n                \"description\": \"List 'Email' records related through the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . emails\",\n                \"description\": \"Relate 'Email' record though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . emails\",\n                \"description\": \"Unrelate 'Email' record related though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/emailsPrimary\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"subject\",\n                                    \"fromName\",\n                                    \"fromAddress\",\n                                    \"fromString\",\n                                    \"replyToString\",\n                                    \"replyToName\",\n                                    \"replyToAddress\",\n                                    \"addressNameMap\",\n                                    \"from\",\n                                    \"to\",\n                                    \"cc\",\n                                    \"bcc\",\n                                    \"replyTo\",\n                                    \"personStringData\",\n                                    \"isRead\",\n                                    \"isNotRead\",\n                                    \"isReplied\",\n                                    \"isNotReplied\",\n                                    \"isImportant\",\n                                    \"inTrash\",\n                                    \"inArchive\",\n                                    \"folderId\",\n                                    \"isUsers\",\n                                    \"isUsersSent\",\n                                    \"folderName\",\n                                    \"folderStringId\",\n                                    \"folderStringName\",\n                                    \"nameHash\",\n                                    \"typeHash\",\n                                    \"idHash\",\n                                    \"messageId\",\n                                    \"messageIdInternal\",\n                                    \"emailAddress\",\n                                    \"fromEmailAddressId\",\n                                    \"fromEmailAddressName\",\n                                    \"toEmailAddressesIds\",\n                                    \"toEmailAddressesNames\",\n                                    \"ccEmailAddressesIds\",\n                                    \"ccEmailAddressesNames\",\n                                    \"bccEmailAddressesIds\",\n                                    \"bccEmailAddressesNames\",\n                                    \"replyToEmailAddressesIds\",\n                                    \"replyToEmailAddressesNames\",\n                                    \"bodyPlain\",\n                                    \"body\",\n                                    \"isHtml\",\n                                    \"status\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"hasAttachment\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"dateSent\",\n                                    \"deliveryDate\",\n                                    \"sendAt\",\n                                    \"isAutoReply\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"sentById\",\n                                    \"sentByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"repliedId\",\n                                    \"repliedName\",\n                                    \"repliesIds\",\n                                    \"repliesNames\",\n                                    \"isSystem\",\n                                    \"isJustSent\",\n                                    \"isBeingImported\",\n                                    \"skipNotificationMap\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"assignedUsersIds\",\n                                    \"assignedUsersNames\",\n                                    \"inboundEmailsIds\",\n                                    \"inboundEmailsNames\",\n                                    \"emailAccountsIds\",\n                                    \"emailAccountsNames\",\n                                    \"icsContents\",\n                                    \"icsEventData\",\n                                    \"icsEventUid\",\n                                    \"icsEventDateStart\",\n                                    \"icsEventDateStartDate\",\n                                    \"createEvent\",\n                                    \"createdEventId\",\n                                    \"createdEventType\",\n                                    \"createdEventName\",\n                                    \"groupFolderId\",\n                                    \"groupFolderName\",\n                                    \"groupStatusFolder\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"tasksIds\",\n                                    \"tasksNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . emailsPrimary\",\n                \"description\": \"List 'Email' records related through the 'emailsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . emailsPrimary\",\n                \"description\": \"Relate 'Email' record though the 'emailsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . emailsPrimary\",\n                \"description\": \"Unrelate 'Email' record related though the 'emailsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/meetings\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"isAllDay\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"joinUrl\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"sourceEmailId\",\n                                    \"sourceEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . meetings\",\n                \"description\": \"List 'Meeting' records related through the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . meetings\",\n                \"description\": \"Relate 'Meeting' record though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . meetings\",\n                \"description\": \"Unrelate 'Meeting' record related though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/meetingsPrimary\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"isAllDay\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"joinUrl\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"sourceEmailId\",\n                                    \"sourceEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . meetingsPrimary\",\n                \"description\": \"List 'Meeting' records related through the 'meetingsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . meetingsPrimary\",\n                \"description\": \"Relate 'Meeting' record though the 'meetingsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . meetingsPrimary\",\n                \"description\": \"Unrelate 'Meeting' record related though the 'meetingsPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/opportunities\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"won\",\n                                \"lost\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"amountCurrency\",\n                                    \"amount\",\n                                    \"amountConverted\",\n                                    \"amountWeightedConverted\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"stage\",\n                                    \"lastStage\",\n                                    \"probability\",\n                                    \"leadSource\",\n                                    \"closeDate\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"contactRole\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . opportunities\",\n                \"description\": \"List 'Opportunity' records related through the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . opportunities\",\n                \"description\": \"Relate 'Opportunity' record though the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . opportunities\",\n                \"description\": \"Unrelate 'Opportunity' record related though the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/portalUsers\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"activePortal\",\n                                \"activeApi\",\n                                \"portal\",\n                                \"api\",\n                                \"internal\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMyTeam\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"userName\",\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"type\",\n                                    \"authMethod\",\n                                    \"apiKey\",\n                                    \"secretKey\",\n                                    \"isActive\",\n                                    \"title\",\n                                    \"position\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"token\",\n                                    \"authTokenId\",\n                                    \"ipAddress\",\n                                    \"defaultTeamId\",\n                                    \"defaultTeamName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamRole\",\n                                    \"teamsIds\",\n                                    \"teamsColumns\",\n                                    \"teamsNames\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"portalRolesIds\",\n                                    \"portalRolesNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"portalId\",\n                                    \"portalName\",\n                                    \"avatarId\",\n                                    \"avatarName\",\n                                    \"avatarColor\",\n                                    \"sendAccessInfo\",\n                                    \"gender\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"dashboardTemplateId\",\n                                    \"dashboardTemplateName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"auth2FA\",\n                                    \"lastAccess\",\n                                    \"emailAddressList\",\n                                    \"userEmailAddressList\",\n                                    \"excludeFromReplyEmailAddressList\",\n                                    \"recordAccessLevels\",\n                                    \"targetListIsOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . portalUsers\",\n                \"description\": \"List 'User' records related through the 'portalUsers' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . portalUsers\",\n                \"description\": \"Relate 'User' record though the 'portalUsers' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . portalUsers\",\n                \"description\": \"Unrelate 'User' record related though the 'portalUsers' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/targetLists\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"categoryId\",\n                                    \"categoryName\",\n                                    \"entryCount\",\n                                    \"optedOutCount\",\n                                    \"description\",\n                                    \"sourceCampaignId\",\n                                    \"sourceCampaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"includingActionList\",\n                                    \"excludingActionList\",\n                                    \"targetStatus\",\n                                    \"isOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . targetLists\",\n                \"description\": \"List 'TargetList' records related through the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . targetLists\",\n                \"description\": \"Relate 'TargetList' record though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . targetLists\",\n                \"description\": \"Unrelate 'TargetList' record related though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/tasks\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . tasks\",\n                \"description\": \"List 'Task' records related through the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . tasks\",\n                \"description\": \"Relate 'Task' record though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . tasks\",\n                \"description\": \"Unrelate 'Task' record related though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/tasksPrimary\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . tasksPrimary\",\n                \"description\": \"List 'Task' records related through the 'tasksPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . tasksPrimary\",\n                \"description\": \"Relate 'Task' record though the 'tasksPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . tasksPrimary\",\n                \"description\": \"Unrelate 'Task' record related though the 'tasksPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Account\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Account . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Account . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Account\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Account . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Call\": {\n            \"post\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Call_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Call\",\n                \"description\": \"Create a new 'Call' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateEnd\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"direction\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"phoneNumbersMap\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Call\",\n                \"description\": \"List Call records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Call\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"summary\": \"Read Call\",\n                \"description\": \"Read an existing 'Call' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [],\n                \"summary\": \"Update Call\",\n                \"description\": \"Update an existing 'Call' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"summary\": \"Remove Call\",\n                \"description\": \"Remove an existing 'Call' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Call\\/{id}\\/contacts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Call . contacts\",\n                \"description\": \"List 'Contact' records related through the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Call . contacts\",\n                \"description\": \"Relate 'Contact' record though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Call . contacts\",\n                \"description\": \"Unrelate 'Contact' record related though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Call\\/{id}\\/leads\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"active\",\n                                \"converted\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"title\",\n                                    \"status\",\n                                    \"source\",\n                                    \"industry\",\n                                    \"opportunityAmountCurrency\",\n                                    \"opportunityAmount\",\n                                    \"opportunityAmountConverted\",\n                                    \"website\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"description\",\n                                    \"convertedAt\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"accountName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAccountId\",\n                                    \"createdAccountName\",\n                                    \"createdContactId\",\n                                    \"createdContactName\",\n                                    \"createdOpportunityId\",\n                                    \"createdOpportunityName\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Call . leads\",\n                \"description\": \"List 'Lead' records related through the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Call . leads\",\n                \"description\": \"Relate 'Lead' record though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Call . leads\",\n                \"description\": \"Unrelate 'Lead' record related though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Call\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Call . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Call . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Call . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Call\\/{id}\\/users\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"activePortal\",\n                                \"activeApi\",\n                                \"portal\",\n                                \"api\",\n                                \"internal\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMyTeam\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"userName\",\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"type\",\n                                    \"authMethod\",\n                                    \"apiKey\",\n                                    \"secretKey\",\n                                    \"isActive\",\n                                    \"title\",\n                                    \"position\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"token\",\n                                    \"authTokenId\",\n                                    \"ipAddress\",\n                                    \"defaultTeamId\",\n                                    \"defaultTeamName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamRole\",\n                                    \"teamsIds\",\n                                    \"teamsColumns\",\n                                    \"teamsNames\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"portalRolesIds\",\n                                    \"portalRolesNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"portalId\",\n                                    \"portalName\",\n                                    \"avatarId\",\n                                    \"avatarName\",\n                                    \"avatarColor\",\n                                    \"sendAccessInfo\",\n                                    \"gender\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"dashboardTemplateId\",\n                                    \"dashboardTemplateName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"auth2FA\",\n                                    \"lastAccess\",\n                                    \"emailAddressList\",\n                                    \"userEmailAddressList\",\n                                    \"excludeFromReplyEmailAddressList\",\n                                    \"recordAccessLevels\",\n                                    \"targetListIsOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Call . users\",\n                \"description\": \"List 'User' records related through the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Call . users\",\n                \"description\": \"Relate 'User' record though the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Call\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Call . users\",\n                \"description\": \"Unrelate 'User' record related though the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Campaign\": {\n            \"post\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Campaign_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Campaign\",\n                \"description\": \"Create a new 'Campaign' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Campaign\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"type\",\n                                    \"startDate\",\n                                    \"endDate\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"excludingTargetListsIds\",\n                                    \"excludingTargetListsNames\",\n                                    \"sentCount\",\n                                    \"openedCount\",\n                                    \"clickedCount\",\n                                    \"optedInCount\",\n                                    \"optedOutCount\",\n                                    \"bouncedCount\",\n                                    \"hardBouncedCount\",\n                                    \"softBouncedCount\",\n                                    \"leadCreatedCount\",\n                                    \"openedPercentage\",\n                                    \"clickedPercentage\",\n                                    \"optedOutPercentage\",\n                                    \"bouncedPercentage\",\n                                    \"revenueCurrency\",\n                                    \"revenue\",\n                                    \"budgetCurrency\",\n                                    \"budget\",\n                                    \"contactsTemplateId\",\n                                    \"contactsTemplateName\",\n                                    \"leadsTemplateId\",\n                                    \"leadsTemplateName\",\n                                    \"accountsTemplateId\",\n                                    \"accountsTemplateName\",\n                                    \"usersTemplateId\",\n                                    \"usersTemplateName\",\n                                    \"mailMergeOnlyWithAddress\",\n                                    \"revenueConverted\",\n                                    \"budgetConverted\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Campaign\",\n                \"description\": \"List Campaign records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Campaign\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Campaign\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"summary\": \"Read Campaign\",\n                \"description\": \"Read an existing 'Campaign' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Campaign\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Campaign\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [],\n                \"summary\": \"Update Campaign\",\n                \"description\": \"Update an existing 'Campaign' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Campaign\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"summary\": \"Remove Campaign\",\n                \"description\": \"Remove an existing 'Campaign' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Campaign\\/{id}\\/accounts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"customers\",\n                                \"resellers\",\n                                \"partners\",\n                                \"recentlyCreated\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"website\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"type\",\n                                    \"industry\",\n                                    \"sicCode\",\n                                    \"contactRole\",\n                                    \"contactIsInactive\",\n                                    \"billingAddressStreet\",\n                                    \"billingAddressCity\",\n                                    \"billingAddressState\",\n                                    \"billingAddressCountry\",\n                                    \"billingAddressPostalCode\",\n                                    \"shippingAddressStreet\",\n                                    \"shippingAddressCity\",\n                                    \"shippingAddressState\",\n                                    \"shippingAddressCountry\",\n                                    \"shippingAddressPostalCode\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"billingAddressMap\",\n                                    \"shippingAddressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Campaign . accounts\",\n                \"description\": \"List 'Account' records related through the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Campaign . accounts\",\n                \"description\": \"Relate 'Account' record though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Campaign . accounts\",\n                \"description\": \"Unrelate 'Account' record related though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Campaign\\/{id}\\/contacts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Campaign . contacts\",\n                \"description\": \"List 'Contact' records related through the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Campaign . contacts\",\n                \"description\": \"Relate 'Contact' record though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Campaign . contacts\",\n                \"description\": \"Unrelate 'Contact' record related though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Campaign\\/{id}\\/excludingTargetLists\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"categoryId\",\n                                    \"categoryName\",\n                                    \"entryCount\",\n                                    \"optedOutCount\",\n                                    \"description\",\n                                    \"sourceCampaignId\",\n                                    \"sourceCampaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"includingActionList\",\n                                    \"excludingActionList\",\n                                    \"targetStatus\",\n                                    \"isOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Campaign . excludingTargetLists\",\n                \"description\": \"List 'TargetList' records related through the 'excludingTargetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Campaign . excludingTargetLists\",\n                \"description\": \"Relate 'TargetList' record though the 'excludingTargetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Campaign . excludingTargetLists\",\n                \"description\": \"Unrelate 'TargetList' record related though the 'excludingTargetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Campaign\\/{id}\\/leads\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"active\",\n                                \"converted\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"title\",\n                                    \"status\",\n                                    \"source\",\n                                    \"industry\",\n                                    \"opportunityAmountCurrency\",\n                                    \"opportunityAmount\",\n                                    \"opportunityAmountConverted\",\n                                    \"website\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"description\",\n                                    \"convertedAt\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"accountName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAccountId\",\n                                    \"createdAccountName\",\n                                    \"createdContactId\",\n                                    \"createdContactName\",\n                                    \"createdOpportunityId\",\n                                    \"createdOpportunityName\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Campaign . leads\",\n                \"description\": \"List 'Lead' records related through the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Campaign . leads\",\n                \"description\": \"Relate 'Lead' record though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Campaign . leads\",\n                \"description\": \"Unrelate 'Lead' record related though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Campaign\\/{id}\\/opportunities\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"won\",\n                                \"lost\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"amountCurrency\",\n                                    \"amount\",\n                                    \"amountConverted\",\n                                    \"amountWeightedConverted\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"stage\",\n                                    \"lastStage\",\n                                    \"probability\",\n                                    \"leadSource\",\n                                    \"closeDate\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"contactRole\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Campaign . opportunities\",\n                \"description\": \"List 'Opportunity' records related through the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Campaign . opportunities\",\n                \"description\": \"Relate 'Opportunity' record though the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Campaign . opportunities\",\n                \"description\": \"Unrelate 'Opportunity' record related though the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Campaign\\/{id}\\/targetLists\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"categoryId\",\n                                    \"categoryName\",\n                                    \"entryCount\",\n                                    \"optedOutCount\",\n                                    \"description\",\n                                    \"sourceCampaignId\",\n                                    \"sourceCampaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"includingActionList\",\n                                    \"excludingActionList\",\n                                    \"targetStatus\",\n                                    \"isOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Campaign . targetLists\",\n                \"description\": \"List 'TargetList' records related through the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Campaign . targetLists\",\n                \"description\": \"Relate 'TargetList' record though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Campaign . targetLists\",\n                \"description\": \"Unrelate 'TargetList' record related though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Campaign\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Campaign . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Campaign . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Campaign\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Campaign . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\": {\n            \"post\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Case_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Case\",\n                \"description\": \"Create a new 'Case' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"closed\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"number\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"type\",\n                                    \"description\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"leadId\",\n                                    \"leadName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"contactsIds\",\n                                    \"contactsNames\",\n                                    \"inboundEmailId\",\n                                    \"inboundEmailName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"isInternal\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Case\",\n                \"description\": \"List Case records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"summary\": \"Read Case\",\n                \"description\": \"Read an existing 'Case' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Version-Number\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A version number for optimistic concurrency control. Obtained from the 'versionNumber' field.\"\n                    }\n                ],\n                \"summary\": \"Update Case\",\n                \"description\": \"Update an existing 'Case' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"summary\": \"Remove Case\",\n                \"description\": \"Remove an existing 'Case' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\\/{id}\\/articles\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"published\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"language\",\n                                    \"type\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"publishDate\",\n                                    \"expirationDate\",\n                                    \"order\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"categoriesIds\",\n                                    \"categoriesNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"body\",\n                                    \"bodyPlain\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Case . articles\",\n                \"description\": \"List 'KnowledgeBaseArticle' records related through the 'articles' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/KnowledgeBaseArticle\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of KnowledgeBaseArticle record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Case . articles\",\n                \"description\": \"Relate 'KnowledgeBaseArticle' record though the 'articles' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of KnowledgeBaseArticle record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Case . articles\",\n                \"description\": \"Unrelate 'KnowledgeBaseArticle' record related though the 'articles' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\\/{id}\\/calls\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateEnd\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"direction\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"phoneNumbersMap\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Case . calls\",\n                \"description\": \"List 'Call' records related through the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Case . calls\",\n                \"description\": \"Relate 'Call' record though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Case . calls\",\n                \"description\": \"Unrelate 'Call' record related though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\\/{id}\\/collaborators\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"activePortal\",\n                                \"activeApi\",\n                                \"portal\",\n                                \"api\",\n                                \"internal\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMyTeam\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"userName\",\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"type\",\n                                    \"authMethod\",\n                                    \"apiKey\",\n                                    \"secretKey\",\n                                    \"isActive\",\n                                    \"title\",\n                                    \"position\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"token\",\n                                    \"authTokenId\",\n                                    \"ipAddress\",\n                                    \"defaultTeamId\",\n                                    \"defaultTeamName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamRole\",\n                                    \"teamsIds\",\n                                    \"teamsColumns\",\n                                    \"teamsNames\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"portalRolesIds\",\n                                    \"portalRolesNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"portalId\",\n                                    \"portalName\",\n                                    \"avatarId\",\n                                    \"avatarName\",\n                                    \"avatarColor\",\n                                    \"sendAccessInfo\",\n                                    \"gender\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"dashboardTemplateId\",\n                                    \"dashboardTemplateName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"auth2FA\",\n                                    \"lastAccess\",\n                                    \"emailAddressList\",\n                                    \"userEmailAddressList\",\n                                    \"excludeFromReplyEmailAddressList\",\n                                    \"recordAccessLevels\",\n                                    \"targetListIsOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Case . collaborators\",\n                \"description\": \"List 'User' records related through the 'collaborators' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Case . collaborators\",\n                \"description\": \"Relate 'User' record though the 'collaborators' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Case . collaborators\",\n                \"description\": \"Unrelate 'User' record related though the 'collaborators' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\\/{id}\\/contacts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Case . contacts\",\n                \"description\": \"List 'Contact' records related through the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Case . contacts\",\n                \"description\": \"Relate 'Contact' record though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Case . contacts\",\n                \"description\": \"Unrelate 'Contact' record related though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\\/{id}\\/emails\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"subject\",\n                                    \"fromName\",\n                                    \"fromAddress\",\n                                    \"fromString\",\n                                    \"replyToString\",\n                                    \"replyToName\",\n                                    \"replyToAddress\",\n                                    \"addressNameMap\",\n                                    \"from\",\n                                    \"to\",\n                                    \"cc\",\n                                    \"bcc\",\n                                    \"replyTo\",\n                                    \"personStringData\",\n                                    \"isRead\",\n                                    \"isNotRead\",\n                                    \"isReplied\",\n                                    \"isNotReplied\",\n                                    \"isImportant\",\n                                    \"inTrash\",\n                                    \"inArchive\",\n                                    \"folderId\",\n                                    \"isUsers\",\n                                    \"isUsersSent\",\n                                    \"folderName\",\n                                    \"folderStringId\",\n                                    \"folderStringName\",\n                                    \"nameHash\",\n                                    \"typeHash\",\n                                    \"idHash\",\n                                    \"messageId\",\n                                    \"messageIdInternal\",\n                                    \"emailAddress\",\n                                    \"fromEmailAddressId\",\n                                    \"fromEmailAddressName\",\n                                    \"toEmailAddressesIds\",\n                                    \"toEmailAddressesNames\",\n                                    \"ccEmailAddressesIds\",\n                                    \"ccEmailAddressesNames\",\n                                    \"bccEmailAddressesIds\",\n                                    \"bccEmailAddressesNames\",\n                                    \"replyToEmailAddressesIds\",\n                                    \"replyToEmailAddressesNames\",\n                                    \"bodyPlain\",\n                                    \"body\",\n                                    \"isHtml\",\n                                    \"status\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"hasAttachment\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"dateSent\",\n                                    \"deliveryDate\",\n                                    \"sendAt\",\n                                    \"isAutoReply\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"sentById\",\n                                    \"sentByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"repliedId\",\n                                    \"repliedName\",\n                                    \"repliesIds\",\n                                    \"repliesNames\",\n                                    \"isSystem\",\n                                    \"isJustSent\",\n                                    \"isBeingImported\",\n                                    \"skipNotificationMap\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"assignedUsersIds\",\n                                    \"assignedUsersNames\",\n                                    \"inboundEmailsIds\",\n                                    \"inboundEmailsNames\",\n                                    \"emailAccountsIds\",\n                                    \"emailAccountsNames\",\n                                    \"icsContents\",\n                                    \"icsEventData\",\n                                    \"icsEventUid\",\n                                    \"icsEventDateStart\",\n                                    \"icsEventDateStartDate\",\n                                    \"createEvent\",\n                                    \"createdEventId\",\n                                    \"createdEventType\",\n                                    \"createdEventName\",\n                                    \"groupFolderId\",\n                                    \"groupFolderName\",\n                                    \"groupStatusFolder\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"tasksIds\",\n                                    \"tasksNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Case . emails\",\n                \"description\": \"List 'Email' records related through the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Case . emails\",\n                \"description\": \"Relate 'Email' record though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Case . emails\",\n                \"description\": \"Unrelate 'Email' record related though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\\/{id}\\/meetings\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"isAllDay\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"joinUrl\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"sourceEmailId\",\n                                    \"sourceEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Case . meetings\",\n                \"description\": \"List 'Meeting' records related through the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Case . meetings\",\n                \"description\": \"Relate 'Meeting' record though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Case . meetings\",\n                \"description\": \"Unrelate 'Meeting' record related though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\\/{id}\\/tasks\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Case . tasks\",\n                \"description\": \"List 'Task' records related through the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Case . tasks\",\n                \"description\": \"Relate 'Task' record though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Case . tasks\",\n                \"description\": \"Unrelate 'Task' record related though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Case\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Case . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Case . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Case\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Case . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\": {\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Contact_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Contact\",\n                \"description\": \"Create a new 'Contact' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact\",\n                \"description\": \"List Contact records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"summary\": \"Read Contact\",\n                \"description\": \"Read an existing 'Contact' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [],\n                \"summary\": \"Update Contact\",\n                \"description\": \"Update an existing 'Contact' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"summary\": \"Remove Contact\",\n                \"description\": \"Remove an existing 'Contact' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/accounts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"customers\",\n                                \"resellers\",\n                                \"partners\",\n                                \"recentlyCreated\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"website\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"type\",\n                                    \"industry\",\n                                    \"sicCode\",\n                                    \"contactRole\",\n                                    \"contactIsInactive\",\n                                    \"billingAddressStreet\",\n                                    \"billingAddressCity\",\n                                    \"billingAddressState\",\n                                    \"billingAddressCountry\",\n                                    \"billingAddressPostalCode\",\n                                    \"shippingAddressStreet\",\n                                    \"shippingAddressCity\",\n                                    \"shippingAddressState\",\n                                    \"shippingAddressCountry\",\n                                    \"shippingAddressPostalCode\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"billingAddressMap\",\n                                    \"shippingAddressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . accounts\",\n                \"description\": \"List 'Account' records related through the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . accounts\",\n                \"description\": \"Relate 'Account' record though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . accounts\",\n                \"description\": \"Unrelate 'Account' record related though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/calls\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateEnd\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"direction\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"phoneNumbersMap\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . calls\",\n                \"description\": \"List 'Call' records related through the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . calls\",\n                \"description\": \"Relate 'Call' record though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . calls\",\n                \"description\": \"Unrelate 'Call' record related though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/cases\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"closed\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"number\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"type\",\n                                    \"description\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"leadId\",\n                                    \"leadName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"contactsIds\",\n                                    \"contactsNames\",\n                                    \"inboundEmailId\",\n                                    \"inboundEmailName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"isInternal\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . cases\",\n                \"description\": \"List 'Case' records related through the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . cases\",\n                \"description\": \"Relate 'Case' record though the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . cases\",\n                \"description\": \"Unrelate 'Case' record related though the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/casesPrimary\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"closed\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"number\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"type\",\n                                    \"description\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"leadId\",\n                                    \"leadName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"contactsIds\",\n                                    \"contactsNames\",\n                                    \"inboundEmailId\",\n                                    \"inboundEmailName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"isInternal\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . casesPrimary\",\n                \"description\": \"List 'Case' records related through the 'casesPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . casesPrimary\",\n                \"description\": \"Relate 'Case' record though the 'casesPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . casesPrimary\",\n                \"description\": \"Unrelate 'Case' record related though the 'casesPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/documents\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"draft\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"fileId\",\n                                    \"fileName\",\n                                    \"status\",\n                                    \"type\",\n                                    \"publishDate\",\n                                    \"expirationDate\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"folderId\",\n                                    \"folderName\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . documents\",\n                \"description\": \"List 'Document' records related through the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Document\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Document record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . documents\",\n                \"description\": \"Relate 'Document' record though the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Document record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . documents\",\n                \"description\": \"Unrelate 'Document' record related though the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/emails\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"subject\",\n                                    \"fromName\",\n                                    \"fromAddress\",\n                                    \"fromString\",\n                                    \"replyToString\",\n                                    \"replyToName\",\n                                    \"replyToAddress\",\n                                    \"addressNameMap\",\n                                    \"from\",\n                                    \"to\",\n                                    \"cc\",\n                                    \"bcc\",\n                                    \"replyTo\",\n                                    \"personStringData\",\n                                    \"isRead\",\n                                    \"isNotRead\",\n                                    \"isReplied\",\n                                    \"isNotReplied\",\n                                    \"isImportant\",\n                                    \"inTrash\",\n                                    \"inArchive\",\n                                    \"folderId\",\n                                    \"isUsers\",\n                                    \"isUsersSent\",\n                                    \"folderName\",\n                                    \"folderStringId\",\n                                    \"folderStringName\",\n                                    \"nameHash\",\n                                    \"typeHash\",\n                                    \"idHash\",\n                                    \"messageId\",\n                                    \"messageIdInternal\",\n                                    \"emailAddress\",\n                                    \"fromEmailAddressId\",\n                                    \"fromEmailAddressName\",\n                                    \"toEmailAddressesIds\",\n                                    \"toEmailAddressesNames\",\n                                    \"ccEmailAddressesIds\",\n                                    \"ccEmailAddressesNames\",\n                                    \"bccEmailAddressesIds\",\n                                    \"bccEmailAddressesNames\",\n                                    \"replyToEmailAddressesIds\",\n                                    \"replyToEmailAddressesNames\",\n                                    \"bodyPlain\",\n                                    \"body\",\n                                    \"isHtml\",\n                                    \"status\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"hasAttachment\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"dateSent\",\n                                    \"deliveryDate\",\n                                    \"sendAt\",\n                                    \"isAutoReply\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"sentById\",\n                                    \"sentByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"repliedId\",\n                                    \"repliedName\",\n                                    \"repliesIds\",\n                                    \"repliesNames\",\n                                    \"isSystem\",\n                                    \"isJustSent\",\n                                    \"isBeingImported\",\n                                    \"skipNotificationMap\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"assignedUsersIds\",\n                                    \"assignedUsersNames\",\n                                    \"inboundEmailsIds\",\n                                    \"inboundEmailsNames\",\n                                    \"emailAccountsIds\",\n                                    \"emailAccountsNames\",\n                                    \"icsContents\",\n                                    \"icsEventData\",\n                                    \"icsEventUid\",\n                                    \"icsEventDateStart\",\n                                    \"icsEventDateStartDate\",\n                                    \"createEvent\",\n                                    \"createdEventId\",\n                                    \"createdEventType\",\n                                    \"createdEventName\",\n                                    \"groupFolderId\",\n                                    \"groupFolderName\",\n                                    \"groupStatusFolder\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"tasksIds\",\n                                    \"tasksNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . emails\",\n                \"description\": \"List 'Email' records related through the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . emails\",\n                \"description\": \"Relate 'Email' record though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . emails\",\n                \"description\": \"Unrelate 'Email' record related though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/meetings\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"isAllDay\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"joinUrl\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"sourceEmailId\",\n                                    \"sourceEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . meetings\",\n                \"description\": \"List 'Meeting' records related through the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . meetings\",\n                \"description\": \"Relate 'Meeting' record though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . meetings\",\n                \"description\": \"Unrelate 'Meeting' record related though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/opportunities\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"won\",\n                                \"lost\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"amountCurrency\",\n                                    \"amount\",\n                                    \"amountConverted\",\n                                    \"amountWeightedConverted\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"stage\",\n                                    \"lastStage\",\n                                    \"probability\",\n                                    \"leadSource\",\n                                    \"closeDate\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"contactRole\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . opportunities\",\n                \"description\": \"List 'Opportunity' records related through the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . opportunities\",\n                \"description\": \"Relate 'Opportunity' record though the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . opportunities\",\n                \"description\": \"Unrelate 'Opportunity' record related though the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/opportunitiesPrimary\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"won\",\n                                \"lost\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"amountCurrency\",\n                                    \"amount\",\n                                    \"amountConverted\",\n                                    \"amountWeightedConverted\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"stage\",\n                                    \"lastStage\",\n                                    \"probability\",\n                                    \"leadSource\",\n                                    \"closeDate\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"contactRole\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . opportunitiesPrimary\",\n                \"description\": \"List 'Opportunity' records related through the 'opportunitiesPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . opportunitiesPrimary\",\n                \"description\": \"Relate 'Opportunity' record though the 'opportunitiesPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . opportunitiesPrimary\",\n                \"description\": \"Unrelate 'Opportunity' record related though the 'opportunitiesPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/targetLists\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"categoryId\",\n                                    \"categoryName\",\n                                    \"entryCount\",\n                                    \"optedOutCount\",\n                                    \"description\",\n                                    \"sourceCampaignId\",\n                                    \"sourceCampaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"includingActionList\",\n                                    \"excludingActionList\",\n                                    \"targetStatus\",\n                                    \"isOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . targetLists\",\n                \"description\": \"List 'TargetList' records related through the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . targetLists\",\n                \"description\": \"Relate 'TargetList' record though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . targetLists\",\n                \"description\": \"Unrelate 'TargetList' record related though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/tasks\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . tasks\",\n                \"description\": \"List 'Task' records related through the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . tasks\",\n                \"description\": \"Relate 'Task' record though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . tasks\",\n                \"description\": \"Unrelate 'Task' record related though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/tasksPrimary\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . tasksPrimary\",\n                \"description\": \"List 'Task' records related through the 'tasksPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . tasksPrimary\",\n                \"description\": \"Relate 'Task' record though the 'tasksPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . tasksPrimary\",\n                \"description\": \"Unrelate 'Task' record related though the 'tasksPrimary' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Contact\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Contact . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Contact . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Contact\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Contact . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Document\": {\n            \"post\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Document_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Document\",\n                \"description\": \"Create a new 'Document' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Document\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"draft\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"fileId\",\n                                    \"fileName\",\n                                    \"status\",\n                                    \"type\",\n                                    \"publishDate\",\n                                    \"expirationDate\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"folderId\",\n                                    \"folderName\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Document\",\n                \"description\": \"List Document records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Document\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Document\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"summary\": \"Read Document\",\n                \"description\": \"Read an existing 'Document' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Document\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Document\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [],\n                \"summary\": \"Update Document\",\n                \"description\": \"Update an existing 'Document' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Document\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"summary\": \"Remove Document\",\n                \"description\": \"Remove an existing 'Document' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Document\\/{id}\\/accounts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"customers\",\n                                \"resellers\",\n                                \"partners\",\n                                \"recentlyCreated\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"website\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"type\",\n                                    \"industry\",\n                                    \"sicCode\",\n                                    \"contactRole\",\n                                    \"contactIsInactive\",\n                                    \"billingAddressStreet\",\n                                    \"billingAddressCity\",\n                                    \"billingAddressState\",\n                                    \"billingAddressCountry\",\n                                    \"billingAddressPostalCode\",\n                                    \"shippingAddressStreet\",\n                                    \"shippingAddressCity\",\n                                    \"shippingAddressState\",\n                                    \"shippingAddressCountry\",\n                                    \"shippingAddressPostalCode\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"billingAddressMap\",\n                                    \"shippingAddressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Document . accounts\",\n                \"description\": \"List 'Account' records related through the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Document . accounts\",\n                \"description\": \"Relate 'Account' record though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Document . accounts\",\n                \"description\": \"Unrelate 'Account' record related though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Document\\/{id}\\/contacts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Document . contacts\",\n                \"description\": \"List 'Contact' records related through the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Document . contacts\",\n                \"description\": \"Relate 'Contact' record though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Document . contacts\",\n                \"description\": \"Unrelate 'Contact' record related though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Document\\/{id}\\/leads\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"active\",\n                                \"converted\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"title\",\n                                    \"status\",\n                                    \"source\",\n                                    \"industry\",\n                                    \"opportunityAmountCurrency\",\n                                    \"opportunityAmount\",\n                                    \"opportunityAmountConverted\",\n                                    \"website\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"description\",\n                                    \"convertedAt\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"accountName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAccountId\",\n                                    \"createdAccountName\",\n                                    \"createdContactId\",\n                                    \"createdContactName\",\n                                    \"createdOpportunityId\",\n                                    \"createdOpportunityName\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Document . leads\",\n                \"description\": \"List 'Lead' records related through the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Document . leads\",\n                \"description\": \"Relate 'Lead' record though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Document . leads\",\n                \"description\": \"Unrelate 'Lead' record related though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Document\\/{id}\\/opportunities\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"won\",\n                                \"lost\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"amountCurrency\",\n                                    \"amount\",\n                                    \"amountConverted\",\n                                    \"amountWeightedConverted\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"stage\",\n                                    \"lastStage\",\n                                    \"probability\",\n                                    \"leadSource\",\n                                    \"closeDate\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"contactRole\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Document . opportunities\",\n                \"description\": \"List 'Opportunity' records related through the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Document . opportunities\",\n                \"description\": \"Relate 'Opportunity' record though the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Opportunity record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Document . opportunities\",\n                \"description\": \"Unrelate 'Opportunity' record related though the 'opportunities' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Document\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Document . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Document . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Document\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Document . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Email\": {\n            \"post\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Email_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Email\",\n                \"description\": \"Create a new 'Email' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"subject\",\n                                    \"fromName\",\n                                    \"fromAddress\",\n                                    \"fromString\",\n                                    \"replyToString\",\n                                    \"replyToName\",\n                                    \"replyToAddress\",\n                                    \"addressNameMap\",\n                                    \"from\",\n                                    \"to\",\n                                    \"cc\",\n                                    \"bcc\",\n                                    \"replyTo\",\n                                    \"personStringData\",\n                                    \"isRead\",\n                                    \"isNotRead\",\n                                    \"isReplied\",\n                                    \"isNotReplied\",\n                                    \"isImportant\",\n                                    \"inTrash\",\n                                    \"inArchive\",\n                                    \"folderId\",\n                                    \"isUsers\",\n                                    \"isUsersSent\",\n                                    \"folderName\",\n                                    \"folderStringId\",\n                                    \"folderStringName\",\n                                    \"nameHash\",\n                                    \"typeHash\",\n                                    \"idHash\",\n                                    \"messageId\",\n                                    \"messageIdInternal\",\n                                    \"emailAddress\",\n                                    \"fromEmailAddressId\",\n                                    \"fromEmailAddressName\",\n                                    \"toEmailAddressesIds\",\n                                    \"toEmailAddressesNames\",\n                                    \"ccEmailAddressesIds\",\n                                    \"ccEmailAddressesNames\",\n                                    \"bccEmailAddressesIds\",\n                                    \"bccEmailAddressesNames\",\n                                    \"replyToEmailAddressesIds\",\n                                    \"replyToEmailAddressesNames\",\n                                    \"bodyPlain\",\n                                    \"body\",\n                                    \"isHtml\",\n                                    \"status\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"hasAttachment\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"dateSent\",\n                                    \"deliveryDate\",\n                                    \"sendAt\",\n                                    \"isAutoReply\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"sentById\",\n                                    \"sentByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"repliedId\",\n                                    \"repliedName\",\n                                    \"repliesIds\",\n                                    \"repliesNames\",\n                                    \"isSystem\",\n                                    \"isJustSent\",\n                                    \"isBeingImported\",\n                                    \"skipNotificationMap\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"assignedUsersIds\",\n                                    \"assignedUsersNames\",\n                                    \"inboundEmailsIds\",\n                                    \"inboundEmailsNames\",\n                                    \"emailAccountsIds\",\n                                    \"emailAccountsNames\",\n                                    \"icsContents\",\n                                    \"icsEventData\",\n                                    \"icsEventUid\",\n                                    \"icsEventDateStart\",\n                                    \"icsEventDateStartDate\",\n                                    \"createEvent\",\n                                    \"createdEventId\",\n                                    \"createdEventType\",\n                                    \"createdEventName\",\n                                    \"groupFolderId\",\n                                    \"groupFolderName\",\n                                    \"groupStatusFolder\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"tasksIds\",\n                                    \"tasksNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Email\",\n                \"description\": \"List Email records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Email\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"summary\": \"Read Email\",\n                \"description\": \"Read an existing 'Email' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [],\n                \"summary\": \"Update Email\",\n                \"description\": \"Update an existing 'Email' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"summary\": \"Remove Email\",\n                \"description\": \"Remove an existing 'Email' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Email\\/{id}\\/assignedUsers\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"activePortal\",\n                                \"activeApi\",\n                                \"portal\",\n                                \"api\",\n                                \"internal\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMyTeam\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"userName\",\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"type\",\n                                    \"authMethod\",\n                                    \"apiKey\",\n                                    \"secretKey\",\n                                    \"isActive\",\n                                    \"title\",\n                                    \"position\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"token\",\n                                    \"authTokenId\",\n                                    \"ipAddress\",\n                                    \"defaultTeamId\",\n                                    \"defaultTeamName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamRole\",\n                                    \"teamsIds\",\n                                    \"teamsColumns\",\n                                    \"teamsNames\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"portalRolesIds\",\n                                    \"portalRolesNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"portalId\",\n                                    \"portalName\",\n                                    \"avatarId\",\n                                    \"avatarName\",\n                                    \"avatarColor\",\n                                    \"sendAccessInfo\",\n                                    \"gender\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"dashboardTemplateId\",\n                                    \"dashboardTemplateName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"auth2FA\",\n                                    \"lastAccess\",\n                                    \"emailAddressList\",\n                                    \"userEmailAddressList\",\n                                    \"excludeFromReplyEmailAddressList\",\n                                    \"recordAccessLevels\",\n                                    \"targetListIsOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Email . assignedUsers\",\n                \"description\": \"List 'User' records related through the 'assignedUsers' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Email . assignedUsers\",\n                \"description\": \"Relate 'User' record though the 'assignedUsers' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Email . assignedUsers\",\n                \"description\": \"Unrelate 'User' record related though the 'assignedUsers' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Email\\/{id}\\/replies\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"subject\",\n                                    \"fromName\",\n                                    \"fromAddress\",\n                                    \"fromString\",\n                                    \"replyToString\",\n                                    \"replyToName\",\n                                    \"replyToAddress\",\n                                    \"addressNameMap\",\n                                    \"from\",\n                                    \"to\",\n                                    \"cc\",\n                                    \"bcc\",\n                                    \"replyTo\",\n                                    \"personStringData\",\n                                    \"isRead\",\n                                    \"isNotRead\",\n                                    \"isReplied\",\n                                    \"isNotReplied\",\n                                    \"isImportant\",\n                                    \"inTrash\",\n                                    \"inArchive\",\n                                    \"folderId\",\n                                    \"isUsers\",\n                                    \"isUsersSent\",\n                                    \"folderName\",\n                                    \"folderStringId\",\n                                    \"folderStringName\",\n                                    \"nameHash\",\n                                    \"typeHash\",\n                                    \"idHash\",\n                                    \"messageId\",\n                                    \"messageIdInternal\",\n                                    \"emailAddress\",\n                                    \"fromEmailAddressId\",\n                                    \"fromEmailAddressName\",\n                                    \"toEmailAddressesIds\",\n                                    \"toEmailAddressesNames\",\n                                    \"ccEmailAddressesIds\",\n                                    \"ccEmailAddressesNames\",\n                                    \"bccEmailAddressesIds\",\n                                    \"bccEmailAddressesNames\",\n                                    \"replyToEmailAddressesIds\",\n                                    \"replyToEmailAddressesNames\",\n                                    \"bodyPlain\",\n                                    \"body\",\n                                    \"isHtml\",\n                                    \"status\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"hasAttachment\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"dateSent\",\n                                    \"deliveryDate\",\n                                    \"sendAt\",\n                                    \"isAutoReply\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"sentById\",\n                                    \"sentByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"repliedId\",\n                                    \"repliedName\",\n                                    \"repliesIds\",\n                                    \"repliesNames\",\n                                    \"isSystem\",\n                                    \"isJustSent\",\n                                    \"isBeingImported\",\n                                    \"skipNotificationMap\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"assignedUsersIds\",\n                                    \"assignedUsersNames\",\n                                    \"inboundEmailsIds\",\n                                    \"inboundEmailsNames\",\n                                    \"emailAccountsIds\",\n                                    \"emailAccountsNames\",\n                                    \"icsContents\",\n                                    \"icsEventData\",\n                                    \"icsEventUid\",\n                                    \"icsEventDateStart\",\n                                    \"icsEventDateStartDate\",\n                                    \"createEvent\",\n                                    \"createdEventId\",\n                                    \"createdEventType\",\n                                    \"createdEventName\",\n                                    \"groupFolderId\",\n                                    \"groupFolderName\",\n                                    \"groupStatusFolder\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"tasksIds\",\n                                    \"tasksNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Email . replies\",\n                \"description\": \"List 'Email' records related through the 'replies' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Email . replies\",\n                \"description\": \"Relate 'Email' record though the 'replies' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Email . replies\",\n                \"description\": \"Unrelate 'Email' record related though the 'replies' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Email\\/{id}\\/tasks\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Email . tasks\",\n                \"description\": \"List 'Task' records related through the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Email . tasks\",\n                \"description\": \"Relate 'Task' record though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Email . tasks\",\n                \"description\": \"Unrelate 'Task' record related though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Email\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Email . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Email . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Email . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Email\\/{id}\\/users\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"activePortal\",\n                                \"activeApi\",\n                                \"portal\",\n                                \"api\",\n                                \"internal\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMyTeam\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"userName\",\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"type\",\n                                    \"authMethod\",\n                                    \"apiKey\",\n                                    \"secretKey\",\n                                    \"isActive\",\n                                    \"title\",\n                                    \"position\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"token\",\n                                    \"authTokenId\",\n                                    \"ipAddress\",\n                                    \"defaultTeamId\",\n                                    \"defaultTeamName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamRole\",\n                                    \"teamsIds\",\n                                    \"teamsColumns\",\n                                    \"teamsNames\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"portalRolesIds\",\n                                    \"portalRolesNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"portalId\",\n                                    \"portalName\",\n                                    \"avatarId\",\n                                    \"avatarName\",\n                                    \"avatarColor\",\n                                    \"sendAccessInfo\",\n                                    \"gender\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"dashboardTemplateId\",\n                                    \"dashboardTemplateName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"auth2FA\",\n                                    \"lastAccess\",\n                                    \"emailAddressList\",\n                                    \"userEmailAddressList\",\n                                    \"excludeFromReplyEmailAddressList\",\n                                    \"recordAccessLevels\",\n                                    \"targetListIsOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Email . users\",\n                \"description\": \"List 'User' records related through the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Email . users\",\n                \"description\": \"Relate 'User' record though the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Email\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Email . users\",\n                \"description\": \"Unrelate 'User' record related though the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/KnowledgeBaseArticle\": {\n            \"post\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/KnowledgeBaseArticle_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create KnowledgeBaseArticle\",\n                \"description\": \"Create a new 'KnowledgeBaseArticle' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/KnowledgeBaseArticle\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"published\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"language\",\n                                    \"type\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"publishDate\",\n                                    \"expirationDate\",\n                                    \"order\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"categoriesIds\",\n                                    \"categoriesNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"body\",\n                                    \"bodyPlain\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List KnowledgeBaseArticle\",\n                \"description\": \"List KnowledgeBaseArticle records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/KnowledgeBaseArticle\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/KnowledgeBaseArticle\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"summary\": \"Read KnowledgeBaseArticle\",\n                \"description\": \"Read an existing 'KnowledgeBaseArticle' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/KnowledgeBaseArticle\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/KnowledgeBaseArticle\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Version-Number\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A version number for optimistic concurrency control. Obtained from the 'versionNumber' field.\"\n                    }\n                ],\n                \"summary\": \"Update KnowledgeBaseArticle\",\n                \"description\": \"Update an existing 'KnowledgeBaseArticle' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/KnowledgeBaseArticle\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"summary\": \"Remove KnowledgeBaseArticle\",\n                \"description\": \"Remove an existing 'KnowledgeBaseArticle' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/KnowledgeBaseArticle\\/{id}\\/cases\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"closed\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"number\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"type\",\n                                    \"description\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"leadId\",\n                                    \"leadName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"contactsIds\",\n                                    \"contactsNames\",\n                                    \"inboundEmailId\",\n                                    \"inboundEmailName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"isInternal\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List KnowledgeBaseArticle . cases\",\n                \"description\": \"List 'Case' records related through the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate KnowledgeBaseArticle . cases\",\n                \"description\": \"Relate 'Case' record though the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate KnowledgeBaseArticle . cases\",\n                \"description\": \"Unrelate 'Case' record related though the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/KnowledgeBaseArticle\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List KnowledgeBaseArticle . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate KnowledgeBaseArticle . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"KnowledgeBaseArticle\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate KnowledgeBaseArticle . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\": {\n            \"post\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Lead_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Lead\",\n                \"description\": \"Create a new 'Lead' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"active\",\n                                \"converted\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"title\",\n                                    \"status\",\n                                    \"source\",\n                                    \"industry\",\n                                    \"opportunityAmountCurrency\",\n                                    \"opportunityAmount\",\n                                    \"opportunityAmountConverted\",\n                                    \"website\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"description\",\n                                    \"convertedAt\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"accountName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAccountId\",\n                                    \"createdAccountName\",\n                                    \"createdContactId\",\n                                    \"createdContactName\",\n                                    \"createdOpportunityId\",\n                                    \"createdOpportunityName\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Lead\",\n                \"description\": \"List Lead records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"summary\": \"Read Lead\",\n                \"description\": \"Read an existing 'Lead' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [],\n                \"summary\": \"Update Lead\",\n                \"description\": \"Update an existing 'Lead' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"summary\": \"Remove Lead\",\n                \"description\": \"Remove an existing 'Lead' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\\/{id}\\/calls\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateEnd\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"direction\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"phoneNumbersMap\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Lead . calls\",\n                \"description\": \"List 'Call' records related through the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Lead . calls\",\n                \"description\": \"Relate 'Call' record though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Lead . calls\",\n                \"description\": \"Unrelate 'Call' record related though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\\/{id}\\/cases\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"closed\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"number\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"type\",\n                                    \"description\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"leadId\",\n                                    \"leadName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"contactsIds\",\n                                    \"contactsNames\",\n                                    \"inboundEmailId\",\n                                    \"inboundEmailName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"isInternal\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Lead . cases\",\n                \"description\": \"List 'Case' records related through the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Case\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Lead . cases\",\n                \"description\": \"Relate 'Case' record though the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Case record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Lead . cases\",\n                \"description\": \"Unrelate 'Case' record related though the 'cases' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\\/{id}\\/documents\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"draft\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"fileId\",\n                                    \"fileName\",\n                                    \"status\",\n                                    \"type\",\n                                    \"publishDate\",\n                                    \"expirationDate\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"folderId\",\n                                    \"folderName\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Lead . documents\",\n                \"description\": \"List 'Document' records related through the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Document\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Document record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Lead . documents\",\n                \"description\": \"Relate 'Document' record though the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Document record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Lead . documents\",\n                \"description\": \"Unrelate 'Document' record related though the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\\/{id}\\/emails\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"subject\",\n                                    \"fromName\",\n                                    \"fromAddress\",\n                                    \"fromString\",\n                                    \"replyToString\",\n                                    \"replyToName\",\n                                    \"replyToAddress\",\n                                    \"addressNameMap\",\n                                    \"from\",\n                                    \"to\",\n                                    \"cc\",\n                                    \"bcc\",\n                                    \"replyTo\",\n                                    \"personStringData\",\n                                    \"isRead\",\n                                    \"isNotRead\",\n                                    \"isReplied\",\n                                    \"isNotReplied\",\n                                    \"isImportant\",\n                                    \"inTrash\",\n                                    \"inArchive\",\n                                    \"folderId\",\n                                    \"isUsers\",\n                                    \"isUsersSent\",\n                                    \"folderName\",\n                                    \"folderStringId\",\n                                    \"folderStringName\",\n                                    \"nameHash\",\n                                    \"typeHash\",\n                                    \"idHash\",\n                                    \"messageId\",\n                                    \"messageIdInternal\",\n                                    \"emailAddress\",\n                                    \"fromEmailAddressId\",\n                                    \"fromEmailAddressName\",\n                                    \"toEmailAddressesIds\",\n                                    \"toEmailAddressesNames\",\n                                    \"ccEmailAddressesIds\",\n                                    \"ccEmailAddressesNames\",\n                                    \"bccEmailAddressesIds\",\n                                    \"bccEmailAddressesNames\",\n                                    \"replyToEmailAddressesIds\",\n                                    \"replyToEmailAddressesNames\",\n                                    \"bodyPlain\",\n                                    \"body\",\n                                    \"isHtml\",\n                                    \"status\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"hasAttachment\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"dateSent\",\n                                    \"deliveryDate\",\n                                    \"sendAt\",\n                                    \"isAutoReply\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"sentById\",\n                                    \"sentByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"repliedId\",\n                                    \"repliedName\",\n                                    \"repliesIds\",\n                                    \"repliesNames\",\n                                    \"isSystem\",\n                                    \"isJustSent\",\n                                    \"isBeingImported\",\n                                    \"skipNotificationMap\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"assignedUsersIds\",\n                                    \"assignedUsersNames\",\n                                    \"inboundEmailsIds\",\n                                    \"inboundEmailsNames\",\n                                    \"emailAccountsIds\",\n                                    \"emailAccountsNames\",\n                                    \"icsContents\",\n                                    \"icsEventData\",\n                                    \"icsEventUid\",\n                                    \"icsEventDateStart\",\n                                    \"icsEventDateStartDate\",\n                                    \"createEvent\",\n                                    \"createdEventId\",\n                                    \"createdEventType\",\n                                    \"createdEventName\",\n                                    \"groupFolderId\",\n                                    \"groupFolderName\",\n                                    \"groupStatusFolder\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"tasksIds\",\n                                    \"tasksNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Lead . emails\",\n                \"description\": \"List 'Email' records related through the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Lead . emails\",\n                \"description\": \"Relate 'Email' record though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Lead . emails\",\n                \"description\": \"Unrelate 'Email' record related though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\\/{id}\\/meetings\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"isAllDay\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"joinUrl\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"sourceEmailId\",\n                                    \"sourceEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Lead . meetings\",\n                \"description\": \"List 'Meeting' records related through the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Lead . meetings\",\n                \"description\": \"Relate 'Meeting' record though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Lead . meetings\",\n                \"description\": \"Unrelate 'Meeting' record related though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\\/{id}\\/targetLists\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"categoryId\",\n                                    \"categoryName\",\n                                    \"entryCount\",\n                                    \"optedOutCount\",\n                                    \"description\",\n                                    \"sourceCampaignId\",\n                                    \"sourceCampaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"includingActionList\",\n                                    \"excludingActionList\",\n                                    \"targetStatus\",\n                                    \"isOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Lead . targetLists\",\n                \"description\": \"List 'TargetList' records related through the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Lead . targetLists\",\n                \"description\": \"Relate 'TargetList' record though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Lead . targetLists\",\n                \"description\": \"Unrelate 'TargetList' record related though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\\/{id}\\/tasks\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Lead . tasks\",\n                \"description\": \"List 'Task' records related through the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Lead . tasks\",\n                \"description\": \"Relate 'Task' record though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Lead . tasks\",\n                \"description\": \"Unrelate 'Task' record related though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Lead\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Lead . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Lead . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Lead\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Lead . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Meeting\": {\n            \"post\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Meeting_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Meeting\",\n                \"description\": \"Create a new 'Meeting' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"isAllDay\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"joinUrl\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"sourceEmailId\",\n                                    \"sourceEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Meeting\",\n                \"description\": \"List Meeting records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Meeting\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"summary\": \"Read Meeting\",\n                \"description\": \"Read an existing 'Meeting' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [],\n                \"summary\": \"Update Meeting\",\n                \"description\": \"Update an existing 'Meeting' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"summary\": \"Remove Meeting\",\n                \"description\": \"Remove an existing 'Meeting' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Meeting\\/{id}\\/contacts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Meeting . contacts\",\n                \"description\": \"List 'Contact' records related through the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Meeting . contacts\",\n                \"description\": \"Relate 'Contact' record though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Meeting . contacts\",\n                \"description\": \"Unrelate 'Contact' record related though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Meeting\\/{id}\\/leads\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"active\",\n                                \"converted\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"title\",\n                                    \"status\",\n                                    \"source\",\n                                    \"industry\",\n                                    \"opportunityAmountCurrency\",\n                                    \"opportunityAmount\",\n                                    \"opportunityAmountConverted\",\n                                    \"website\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"description\",\n                                    \"convertedAt\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"accountName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAccountId\",\n                                    \"createdAccountName\",\n                                    \"createdContactId\",\n                                    \"createdContactName\",\n                                    \"createdOpportunityId\",\n                                    \"createdOpportunityName\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Meeting . leads\",\n                \"description\": \"List 'Lead' records related through the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Meeting . leads\",\n                \"description\": \"Relate 'Lead' record though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Meeting . leads\",\n                \"description\": \"Unrelate 'Lead' record related though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Meeting\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Meeting . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Meeting . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Meeting . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Meeting\\/{id}\\/users\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"activePortal\",\n                                \"activeApi\",\n                                \"portal\",\n                                \"api\",\n                                \"internal\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMyTeam\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"userName\",\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"type\",\n                                    \"authMethod\",\n                                    \"apiKey\",\n                                    \"secretKey\",\n                                    \"isActive\",\n                                    \"title\",\n                                    \"position\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"token\",\n                                    \"authTokenId\",\n                                    \"ipAddress\",\n                                    \"defaultTeamId\",\n                                    \"defaultTeamName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamRole\",\n                                    \"teamsIds\",\n                                    \"teamsColumns\",\n                                    \"teamsNames\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"portalRolesIds\",\n                                    \"portalRolesNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"portalId\",\n                                    \"portalName\",\n                                    \"avatarId\",\n                                    \"avatarName\",\n                                    \"avatarColor\",\n                                    \"sendAccessInfo\",\n                                    \"gender\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"dashboardTemplateId\",\n                                    \"dashboardTemplateName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"auth2FA\",\n                                    \"lastAccess\",\n                                    \"emailAddressList\",\n                                    \"userEmailAddressList\",\n                                    \"excludeFromReplyEmailAddressList\",\n                                    \"recordAccessLevels\",\n                                    \"targetListIsOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Meeting . users\",\n                \"description\": \"List 'User' records related through the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Meeting . users\",\n                \"description\": \"Relate 'User' record though the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Meeting\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Meeting . users\",\n                \"description\": \"Unrelate 'User' record related though the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Opportunity\": {\n            \"post\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Opportunity_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Opportunity\",\n                \"description\": \"Create a new 'Opportunity' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"open\",\n                                \"won\",\n                                \"lost\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"amountCurrency\",\n                                    \"amount\",\n                                    \"amountConverted\",\n                                    \"amountWeightedConverted\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"stage\",\n                                    \"lastStage\",\n                                    \"probability\",\n                                    \"leadSource\",\n                                    \"closeDate\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"contactRole\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Opportunity\",\n                \"description\": \"List Opportunity records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Opportunity\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"summary\": \"Read Opportunity\",\n                \"description\": \"Read an existing 'Opportunity' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Version-Number\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A version number for optimistic concurrency control. Obtained from the 'versionNumber' field.\"\n                    }\n                ],\n                \"summary\": \"Update Opportunity\",\n                \"description\": \"Update an existing 'Opportunity' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Opportunity\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"summary\": \"Remove Opportunity\",\n                \"description\": \"Remove an existing 'Opportunity' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Opportunity\\/{id}\\/calls\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateEnd\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"direction\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"phoneNumbersMap\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Opportunity . calls\",\n                \"description\": \"List 'Call' records related through the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Opportunity . calls\",\n                \"description\": \"Relate 'Call' record though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Opportunity . calls\",\n                \"description\": \"Unrelate 'Call' record related though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Opportunity\\/{id}\\/contacts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Opportunity . contacts\",\n                \"description\": \"List 'Contact' records related through the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Opportunity . contacts\",\n                \"description\": \"Relate 'Contact' record though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Opportunity . contacts\",\n                \"description\": \"Unrelate 'Contact' record related though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Opportunity\\/{id}\\/documents\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"draft\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"fileId\",\n                                    \"fileName\",\n                                    \"status\",\n                                    \"type\",\n                                    \"publishDate\",\n                                    \"expirationDate\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"folderId\",\n                                    \"folderName\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Opportunity . documents\",\n                \"description\": \"List 'Document' records related through the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Document\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Document record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Opportunity . documents\",\n                \"description\": \"Relate 'Document' record though the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Document record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Opportunity . documents\",\n                \"description\": \"Unrelate 'Document' record related though the 'documents' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Opportunity\\/{id}\\/emails\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"subject\",\n                                    \"fromName\",\n                                    \"fromAddress\",\n                                    \"fromString\",\n                                    \"replyToString\",\n                                    \"replyToName\",\n                                    \"replyToAddress\",\n                                    \"addressNameMap\",\n                                    \"from\",\n                                    \"to\",\n                                    \"cc\",\n                                    \"bcc\",\n                                    \"replyTo\",\n                                    \"personStringData\",\n                                    \"isRead\",\n                                    \"isNotRead\",\n                                    \"isReplied\",\n                                    \"isNotReplied\",\n                                    \"isImportant\",\n                                    \"inTrash\",\n                                    \"inArchive\",\n                                    \"folderId\",\n                                    \"isUsers\",\n                                    \"isUsersSent\",\n                                    \"folderName\",\n                                    \"folderStringId\",\n                                    \"folderStringName\",\n                                    \"nameHash\",\n                                    \"typeHash\",\n                                    \"idHash\",\n                                    \"messageId\",\n                                    \"messageIdInternal\",\n                                    \"emailAddress\",\n                                    \"fromEmailAddressId\",\n                                    \"fromEmailAddressName\",\n                                    \"toEmailAddressesIds\",\n                                    \"toEmailAddressesNames\",\n                                    \"ccEmailAddressesIds\",\n                                    \"ccEmailAddressesNames\",\n                                    \"bccEmailAddressesIds\",\n                                    \"bccEmailAddressesNames\",\n                                    \"replyToEmailAddressesIds\",\n                                    \"replyToEmailAddressesNames\",\n                                    \"bodyPlain\",\n                                    \"body\",\n                                    \"isHtml\",\n                                    \"status\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"hasAttachment\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"dateSent\",\n                                    \"deliveryDate\",\n                                    \"sendAt\",\n                                    \"isAutoReply\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"sentById\",\n                                    \"sentByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"repliedId\",\n                                    \"repliedName\",\n                                    \"repliesIds\",\n                                    \"repliesNames\",\n                                    \"isSystem\",\n                                    \"isJustSent\",\n                                    \"isBeingImported\",\n                                    \"skipNotificationMap\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"assignedUsersIds\",\n                                    \"assignedUsersNames\",\n                                    \"inboundEmailsIds\",\n                                    \"inboundEmailsNames\",\n                                    \"emailAccountsIds\",\n                                    \"emailAccountsNames\",\n                                    \"icsContents\",\n                                    \"icsEventData\",\n                                    \"icsEventUid\",\n                                    \"icsEventDateStart\",\n                                    \"icsEventDateStartDate\",\n                                    \"createEvent\",\n                                    \"createdEventId\",\n                                    \"createdEventType\",\n                                    \"createdEventName\",\n                                    \"groupFolderId\",\n                                    \"groupFolderName\",\n                                    \"groupStatusFolder\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"tasksIds\",\n                                    \"tasksNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Opportunity . emails\",\n                \"description\": \"List 'Email' records related through the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Opportunity . emails\",\n                \"description\": \"Relate 'Email' record though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Opportunity . emails\",\n                \"description\": \"Unrelate 'Email' record related though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Opportunity\\/{id}\\/meetings\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"isAllDay\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"joinUrl\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"sourceEmailId\",\n                                    \"sourceEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Opportunity . meetings\",\n                \"description\": \"List 'Meeting' records related through the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Opportunity . meetings\",\n                \"description\": \"Relate 'Meeting' record though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Opportunity . meetings\",\n                \"description\": \"Unrelate 'Meeting' record related though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Opportunity\\/{id}\\/tasks\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Opportunity . tasks\",\n                \"description\": \"List 'Task' records related through the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Opportunity . tasks\",\n                \"description\": \"Relate 'Task' record though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Opportunity . tasks\",\n                \"description\": \"Unrelate 'Task' record related though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Opportunity\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Opportunity . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Opportunity . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Opportunity\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Opportunity . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/TargetList\": {\n            \"post\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/TargetList_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create TargetList\",\n                \"description\": \"Create a new 'TargetList' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"categoryId\",\n                                    \"categoryName\",\n                                    \"entryCount\",\n                                    \"optedOutCount\",\n                                    \"description\",\n                                    \"sourceCampaignId\",\n                                    \"sourceCampaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"includingActionList\",\n                                    \"excludingActionList\",\n                                    \"targetStatus\",\n                                    \"isOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List TargetList\",\n                \"description\": \"List TargetList records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/TargetList\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"summary\": \"Read TargetList\",\n                \"description\": \"Read an existing 'TargetList' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [],\n                \"summary\": \"Update TargetList\",\n                \"description\": \"Update an existing 'TargetList' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"summary\": \"Remove TargetList\",\n                \"description\": \"Remove an existing 'TargetList' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/TargetList\\/{id}\\/accounts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"customers\",\n                                \"resellers\",\n                                \"partners\",\n                                \"recentlyCreated\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"website\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"type\",\n                                    \"industry\",\n                                    \"sicCode\",\n                                    \"contactRole\",\n                                    \"contactIsInactive\",\n                                    \"billingAddressStreet\",\n                                    \"billingAddressCity\",\n                                    \"billingAddressState\",\n                                    \"billingAddressCountry\",\n                                    \"billingAddressPostalCode\",\n                                    \"shippingAddressStreet\",\n                                    \"shippingAddressCity\",\n                                    \"shippingAddressState\",\n                                    \"shippingAddressCountry\",\n                                    \"shippingAddressPostalCode\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"billingAddressMap\",\n                                    \"shippingAddressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List TargetList . accounts\",\n                \"description\": \"List 'Account' records related through the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate TargetList . accounts\",\n                \"description\": \"Relate 'Account' record though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate TargetList . accounts\",\n                \"description\": \"Unrelate 'Account' record related though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/TargetList\\/{id}\\/campaigns\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"type\",\n                                    \"startDate\",\n                                    \"endDate\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"excludingTargetListsIds\",\n                                    \"excludingTargetListsNames\",\n                                    \"sentCount\",\n                                    \"openedCount\",\n                                    \"clickedCount\",\n                                    \"optedInCount\",\n                                    \"optedOutCount\",\n                                    \"bouncedCount\",\n                                    \"hardBouncedCount\",\n                                    \"softBouncedCount\",\n                                    \"leadCreatedCount\",\n                                    \"openedPercentage\",\n                                    \"clickedPercentage\",\n                                    \"optedOutPercentage\",\n                                    \"bouncedPercentage\",\n                                    \"revenueCurrency\",\n                                    \"revenue\",\n                                    \"budgetCurrency\",\n                                    \"budget\",\n                                    \"contactsTemplateId\",\n                                    \"contactsTemplateName\",\n                                    \"leadsTemplateId\",\n                                    \"leadsTemplateName\",\n                                    \"accountsTemplateId\",\n                                    \"accountsTemplateName\",\n                                    \"usersTemplateId\",\n                                    \"usersTemplateName\",\n                                    \"mailMergeOnlyWithAddress\",\n                                    \"revenueConverted\",\n                                    \"budgetConverted\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List TargetList . campaigns\",\n                \"description\": \"List 'Campaign' records related through the 'campaigns' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Campaign\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Campaign record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate TargetList . campaigns\",\n                \"description\": \"Relate 'Campaign' record though the 'campaigns' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Campaign record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate TargetList . campaigns\",\n                \"description\": \"Unrelate 'Campaign' record related though the 'campaigns' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/TargetList\\/{id}\\/campaignsExcluding\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"type\",\n                                    \"startDate\",\n                                    \"endDate\",\n                                    \"description\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"excludingTargetListsIds\",\n                                    \"excludingTargetListsNames\",\n                                    \"sentCount\",\n                                    \"openedCount\",\n                                    \"clickedCount\",\n                                    \"optedInCount\",\n                                    \"optedOutCount\",\n                                    \"bouncedCount\",\n                                    \"hardBouncedCount\",\n                                    \"softBouncedCount\",\n                                    \"leadCreatedCount\",\n                                    \"openedPercentage\",\n                                    \"clickedPercentage\",\n                                    \"optedOutPercentage\",\n                                    \"bouncedPercentage\",\n                                    \"revenueCurrency\",\n                                    \"revenue\",\n                                    \"budgetCurrency\",\n                                    \"budget\",\n                                    \"contactsTemplateId\",\n                                    \"contactsTemplateName\",\n                                    \"leadsTemplateId\",\n                                    \"leadsTemplateName\",\n                                    \"accountsTemplateId\",\n                                    \"accountsTemplateName\",\n                                    \"usersTemplateId\",\n                                    \"usersTemplateName\",\n                                    \"mailMergeOnlyWithAddress\",\n                                    \"revenueConverted\",\n                                    \"budgetConverted\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List TargetList . campaignsExcluding\",\n                \"description\": \"List 'Campaign' records related through the 'campaignsExcluding' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Campaign\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Campaign record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate TargetList . campaignsExcluding\",\n                \"description\": \"Relate 'Campaign' record though the 'campaignsExcluding' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Campaign record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate TargetList . campaignsExcluding\",\n                \"description\": \"Unrelate 'Campaign' record related though the 'campaignsExcluding' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/TargetList\\/{id}\\/contacts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"portalUsers\",\n                                \"notPortalUsers\",\n                                \"accountActive\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"accountAnyId\",\n                                    \"title\",\n                                    \"description\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"accountsIds\",\n                                    \"accountsColumns\",\n                                    \"accountsNames\",\n                                    \"accountRole\",\n                                    \"accountIsInactive\",\n                                    \"accountType\",\n                                    \"opportunityRole\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"portalUserId\",\n                                    \"portalUserName\",\n                                    \"hasPortalUser\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List TargetList . contacts\",\n                \"description\": \"List 'Contact' records related through the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Contact\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate TargetList . contacts\",\n                \"description\": \"Relate 'Contact' record though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Contact record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate TargetList . contacts\",\n                \"description\": \"Unrelate 'Contact' record related though the 'contacts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/TargetList\\/{id}\\/leads\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"active\",\n                                \"converted\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"title\",\n                                    \"status\",\n                                    \"source\",\n                                    \"industry\",\n                                    \"opportunityAmountCurrency\",\n                                    \"opportunityAmount\",\n                                    \"opportunityAmountConverted\",\n                                    \"website\",\n                                    \"addressStreet\",\n                                    \"addressCity\",\n                                    \"addressState\",\n                                    \"addressCountry\",\n                                    \"addressPostalCode\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"doNotCall\",\n                                    \"description\",\n                                    \"convertedAt\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"accountName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAccountId\",\n                                    \"createdAccountName\",\n                                    \"createdContactId\",\n                                    \"createdContactName\",\n                                    \"createdOpportunityId\",\n                                    \"createdOpportunityName\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"targetListIsOptedOut\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"addressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List TargetList . leads\",\n                \"description\": \"List 'Lead' records related through the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Lead\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate TargetList . leads\",\n                \"description\": \"Relate 'Lead' record though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Lead record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate TargetList . leads\",\n                \"description\": \"Unrelate 'Lead' record related though the 'leads' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/TargetList\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List TargetList . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate TargetList . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate TargetList . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/TargetList\\/{id}\\/users\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"activePortal\",\n                                \"activeApi\",\n                                \"portal\",\n                                \"api\",\n                                \"internal\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMyTeam\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"userName\",\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"type\",\n                                    \"authMethod\",\n                                    \"apiKey\",\n                                    \"secretKey\",\n                                    \"isActive\",\n                                    \"title\",\n                                    \"position\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"token\",\n                                    \"authTokenId\",\n                                    \"ipAddress\",\n                                    \"defaultTeamId\",\n                                    \"defaultTeamName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamRole\",\n                                    \"teamsIds\",\n                                    \"teamsColumns\",\n                                    \"teamsNames\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"portalRolesIds\",\n                                    \"portalRolesNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"portalId\",\n                                    \"portalName\",\n                                    \"avatarId\",\n                                    \"avatarName\",\n                                    \"avatarColor\",\n                                    \"sendAccessInfo\",\n                                    \"gender\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"dashboardTemplateId\",\n                                    \"dashboardTemplateName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"auth2FA\",\n                                    \"lastAccess\",\n                                    \"emailAddressList\",\n                                    \"userEmailAddressList\",\n                                    \"excludeFromReplyEmailAddressList\",\n                                    \"recordAccessLevels\",\n                                    \"targetListIsOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List TargetList . users\",\n                \"description\": \"List 'User' records related through the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate TargetList . users\",\n                \"description\": \"Relate 'User' record though the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"TargetList\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate TargetList . users\",\n                \"description\": \"Unrelate 'User' record related though the 'users' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Task\": {\n            \"post\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Task_create\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Skip-Duplicate-Check\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Skip duplicate check.\"\n                    },\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Duplicate-Source-Id\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A record ID of the entity that is being duplicated.\"\n                    }\n                ],\n                \"summary\": \"Create Task\",\n                \"description\": \"Create a new 'Task' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict. May be a possible duplicate. Use X-Skip-Duplicate-Check to skip check.\"\n                    }\n                }\n            },\n            \"get\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Task\",\n                \"description\": \"List Task records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Task\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"summary\": \"Read Task\",\n                \"description\": \"Read an existing 'Task' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-Version-Number\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A version number for optimistic concurrency control. Obtained from the 'versionNumber' field.\"\n                    }\n                ],\n                \"summary\": \"Update Task\",\n                \"description\": \"Update an existing 'Task' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"summary\": \"Remove Task\",\n                \"description\": \"Remove an existing 'Task' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"boolean\",\n                                    \"description\": \"Always true. Do not check the value.\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Task\\/{id}\\/collaborators\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"activePortal\",\n                                \"activeApi\",\n                                \"portal\",\n                                \"api\",\n                                \"internal\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMyTeam\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"userName\",\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"type\",\n                                    \"authMethod\",\n                                    \"apiKey\",\n                                    \"secretKey\",\n                                    \"isActive\",\n                                    \"title\",\n                                    \"position\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"token\",\n                                    \"authTokenId\",\n                                    \"ipAddress\",\n                                    \"defaultTeamId\",\n                                    \"defaultTeamName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamRole\",\n                                    \"teamsIds\",\n                                    \"teamsColumns\",\n                                    \"teamsNames\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"portalRolesIds\",\n                                    \"portalRolesNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"portalId\",\n                                    \"portalName\",\n                                    \"avatarId\",\n                                    \"avatarName\",\n                                    \"avatarColor\",\n                                    \"sendAccessInfo\",\n                                    \"gender\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"dashboardTemplateId\",\n                                    \"dashboardTemplateName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"auth2FA\",\n                                    \"lastAccess\",\n                                    \"emailAddressList\",\n                                    \"userEmailAddressList\",\n                                    \"excludeFromReplyEmailAddressList\",\n                                    \"recordAccessLevels\",\n                                    \"targetListIsOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Task . collaborators\",\n                \"description\": \"List 'User' records related through the 'collaborators' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Task . collaborators\",\n                \"description\": \"Relate 'User' record though the 'collaborators' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of User record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Task . collaborators\",\n                \"description\": \"Unrelate 'User' record related though the 'collaborators' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Task\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Task . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate Task . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"Task\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate Task . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Team\": {\n            \"get\": {\n                \"tags\": [\n                    \"Team\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List Team\",\n                \"description\": \"List Team records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/Team\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Team\"\n                ],\n                \"summary\": \"Read Team\",\n                \"description\": \"Read an existing 'Team' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/User\": {\n            \"get\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"header\",\n                        \"name\": \"X-No-Total\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"true\",\n                                \"false\"\n                            ]\n                        },\n                        \"description\": \"Disable calculation of the total number of records.\"\n                    },\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"active\",\n                                \"activePortal\",\n                                \"activeApi\",\n                                \"portal\",\n                                \"api\",\n                                \"internal\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMyTeam\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"userName\",\n                                    \"salutationName\",\n                                    \"firstName\",\n                                    \"lastName\",\n                                    \"middleName\",\n                                    \"name\",\n                                    \"type\",\n                                    \"authMethod\",\n                                    \"apiKey\",\n                                    \"secretKey\",\n                                    \"isActive\",\n                                    \"title\",\n                                    \"position\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"token\",\n                                    \"authTokenId\",\n                                    \"ipAddress\",\n                                    \"defaultTeamId\",\n                                    \"defaultTeamName\",\n                                    \"acceptanceStatus\",\n                                    \"acceptanceStatusMeetings\",\n                                    \"acceptanceStatusCalls\",\n                                    \"teamRole\",\n                                    \"teamsIds\",\n                                    \"teamsColumns\",\n                                    \"teamsNames\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"portalsIds\",\n                                    \"portalsNames\",\n                                    \"portalRolesIds\",\n                                    \"portalRolesNames\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"accountsIds\",\n                                    \"accountsNames\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"portalId\",\n                                    \"portalName\",\n                                    \"avatarId\",\n                                    \"avatarName\",\n                                    \"avatarColor\",\n                                    \"sendAccessInfo\",\n                                    \"gender\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"dashboardTemplateId\",\n                                    \"dashboardTemplateName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"auth2FA\",\n                                    \"lastAccess\",\n                                    \"emailAddressList\",\n                                    \"userEmailAddressList\",\n                                    \"excludeFromReplyEmailAddressList\",\n                                    \"recordAccessLevels\",\n                                    \"targetListIsOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List User\",\n                \"description\": \"List User records.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/User\\/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"summary\": \"Read User\",\n                \"description\": \"Read an existing 'User' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"patch\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/User\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [],\n                \"summary\": \"Update User\",\n                \"description\": \"Update an existing 'User' record.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/User\"\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    },\n                    \"409\": {\n                        \"description\": \"Conflict.\"\n                    }\n                }\n            }\n        },\n        \"\\/User\\/{id}\\/accounts\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"customers\",\n                                \"resellers\",\n                                \"partners\",\n                                \"recentlyCreated\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"website\",\n                                    \"emailAddressIsOptedOut\",\n                                    \"emailAddressIsInvalid\",\n                                    \"emailAddress\",\n                                    \"emailAddressData\",\n                                    \"phoneNumberIsOptedOut\",\n                                    \"phoneNumberIsInvalid\",\n                                    \"phoneNumber\",\n                                    \"phoneNumberData\",\n                                    \"type\",\n                                    \"industry\",\n                                    \"sicCode\",\n                                    \"contactRole\",\n                                    \"contactIsInactive\",\n                                    \"billingAddressStreet\",\n                                    \"billingAddressCity\",\n                                    \"billingAddressState\",\n                                    \"billingAddressCountry\",\n                                    \"billingAddressPostalCode\",\n                                    \"shippingAddressStreet\",\n                                    \"shippingAddressCity\",\n                                    \"shippingAddressState\",\n                                    \"shippingAddressCountry\",\n                                    \"shippingAddressPostalCode\",\n                                    \"description\",\n                                    \"campaignId\",\n                                    \"campaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"targetListsIds\",\n                                    \"targetListsNames\",\n                                    \"targetListId\",\n                                    \"targetListName\",\n                                    \"originalLeadId\",\n                                    \"originalLeadName\",\n                                    \"targetListIsOptedOut\",\n                                    \"billingAddressMap\",\n                                    \"shippingAddressMap\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List User . accounts\",\n                \"description\": \"List 'Account' records related through the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Account\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate User . accounts\",\n                \"description\": \"Relate 'Account' record though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Account record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate User . accounts\",\n                \"description\": \"Unrelate 'Account' record related though the 'accounts' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/User\\/{id}\\/calls\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateEnd\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"direction\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"phoneNumbersMap\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List User . calls\",\n                \"description\": \"List 'Call' records related through the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Call\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate User . calls\",\n                \"description\": \"Relate 'Call' record though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Call record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate User . calls\",\n                \"description\": \"Unrelate 'Call' record related though the 'calls' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/User\\/{id}\\/emails\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"subject\",\n                                    \"fromName\",\n                                    \"fromAddress\",\n                                    \"fromString\",\n                                    \"replyToString\",\n                                    \"replyToName\",\n                                    \"replyToAddress\",\n                                    \"addressNameMap\",\n                                    \"from\",\n                                    \"to\",\n                                    \"cc\",\n                                    \"bcc\",\n                                    \"replyTo\",\n                                    \"personStringData\",\n                                    \"isRead\",\n                                    \"isNotRead\",\n                                    \"isReplied\",\n                                    \"isNotReplied\",\n                                    \"isImportant\",\n                                    \"inTrash\",\n                                    \"inArchive\",\n                                    \"folderId\",\n                                    \"isUsers\",\n                                    \"isUsersSent\",\n                                    \"folderName\",\n                                    \"folderStringId\",\n                                    \"folderStringName\",\n                                    \"nameHash\",\n                                    \"typeHash\",\n                                    \"idHash\",\n                                    \"messageId\",\n                                    \"messageIdInternal\",\n                                    \"emailAddress\",\n                                    \"fromEmailAddressId\",\n                                    \"fromEmailAddressName\",\n                                    \"toEmailAddressesIds\",\n                                    \"toEmailAddressesNames\",\n                                    \"ccEmailAddressesIds\",\n                                    \"ccEmailAddressesNames\",\n                                    \"bccEmailAddressesIds\",\n                                    \"bccEmailAddressesNames\",\n                                    \"replyToEmailAddressesIds\",\n                                    \"replyToEmailAddressesNames\",\n                                    \"bodyPlain\",\n                                    \"body\",\n                                    \"isHtml\",\n                                    \"status\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"hasAttachment\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"dateSent\",\n                                    \"deliveryDate\",\n                                    \"sendAt\",\n                                    \"isAutoReply\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"sentById\",\n                                    \"sentByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"repliedId\",\n                                    \"repliedName\",\n                                    \"repliesIds\",\n                                    \"repliesNames\",\n                                    \"isSystem\",\n                                    \"isJustSent\",\n                                    \"isBeingImported\",\n                                    \"skipNotificationMap\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"assignedUsersIds\",\n                                    \"assignedUsersNames\",\n                                    \"inboundEmailsIds\",\n                                    \"inboundEmailsNames\",\n                                    \"emailAccountsIds\",\n                                    \"emailAccountsNames\",\n                                    \"icsContents\",\n                                    \"icsEventData\",\n                                    \"icsEventUid\",\n                                    \"icsEventDateStart\",\n                                    \"icsEventDateStartDate\",\n                                    \"createEvent\",\n                                    \"createdEventId\",\n                                    \"createdEventType\",\n                                    \"createdEventName\",\n                                    \"groupFolderId\",\n                                    \"groupFolderName\",\n                                    \"groupStatusFolder\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"tasksIds\",\n                                    \"tasksNames\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List User . emails\",\n                \"description\": \"List 'Email' records related through the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Email\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate User . emails\",\n                \"description\": \"Relate 'Email' record though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Email record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate User . emails\",\n                \"description\": \"Unrelate 'Email' record related though the 'emails' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/User\\/{id}\\/meetings\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"planned\",\n                                \"held\",\n                                \"todays\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"isAllDay\",\n                                    \"duration\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"uid\",\n                                    \"joinUrl\",\n                                    \"acceptanceStatus\",\n                                    \"usersIds\",\n                                    \"usersColumns\",\n                                    \"usersNames\",\n                                    \"contactsIds\",\n                                    \"contactsColumns\",\n                                    \"contactsNames\",\n                                    \"leadsIds\",\n                                    \"leadsColumns\",\n                                    \"leadsNames\",\n                                    \"sourceEmailId\",\n                                    \"sourceEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List User . meetings\",\n                \"description\": \"List 'Meeting' records related through the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Meeting\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate User . meetings\",\n                \"description\": \"Relate 'Meeting' record though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Meeting record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate User . meetings\",\n                \"description\": \"Unrelate 'Meeting' record related though the 'meetings' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/User\\/{id}\\/targetLists\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"categoryId\",\n                                    \"categoryName\",\n                                    \"entryCount\",\n                                    \"optedOutCount\",\n                                    \"description\",\n                                    \"sourceCampaignId\",\n                                    \"sourceCampaignName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"includingActionList\",\n                                    \"excludingActionList\",\n                                    \"targetStatus\",\n                                    \"isOptedOut\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List User . targetLists\",\n                \"description\": \"List 'TargetList' records related through the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/TargetList\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate User . targetLists\",\n                \"description\": \"Relate 'TargetList' record though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of TargetList record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate User . targetLists\",\n                \"description\": \"Unrelate 'TargetList' record related though the 'targetLists' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/User\\/{id}\\/tasks\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"primaryFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"actual\",\n                                \"completed\",\n                                \"deferred\",\n                                \"todays\",\n                                \"actualStartingNotInFuture\",\n                                \"overdue\"\n                            ]\n                        },\n                        \"description\": \"A primary filter.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"status\",\n                                    \"priority\",\n                                    \"dateStart\",\n                                    \"dateStartDate\",\n                                    \"dateEnd\",\n                                    \"dateEndDate\",\n                                    \"dateCompleted\",\n                                    \"isOverdue\",\n                                    \"reminders\",\n                                    \"description\",\n                                    \"parentId\",\n                                    \"parentType\",\n                                    \"parentName\",\n                                    \"accountId\",\n                                    \"accountName\",\n                                    \"contactId\",\n                                    \"contactName\",\n                                    \"originalEmailId\",\n                                    \"originalEmailName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\",\n                                    \"createdById\",\n                                    \"createdByName\",\n                                    \"modifiedById\",\n                                    \"modifiedByName\",\n                                    \"assignedUserId\",\n                                    \"assignedUserName\",\n                                    \"teamsIds\",\n                                    \"teamsNames\",\n                                    \"attachmentsIds\",\n                                    \"attachmentsNames\",\n                                    \"attachmentsTypes\",\n                                    \"collaboratorsIds\",\n                                    \"collaboratorsNames\",\n                                    \"streamUpdatedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List User . tasks\",\n                \"description\": \"List 'Task' records related through the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Task\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate User . tasks\",\n                \"description\": \"Relate 'Task' record though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Task record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate User . tasks\",\n                \"description\": \"Unrelate 'Task' record related though the 'tasks' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        },\n        \"\\/User\\/{id}\\/teams\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"schema\": {\n                        \"type\": \"string\"\n                    },\n                    \"description\": \"A record ID.\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"offset\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0\n                        },\n                        \"description\": \"A pagination offset.\"\n                    },\n                    {\n                        \"name\": \"maxSize\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"integer\",\n                            \"minimum\": 0,\n                            \"maximum\": 200\n                        },\n                        \"description\": \"The maximum number of records to return.\"\n                    },\n                    {\n                        \"name\": \"orderBy\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"An attribute (field) to order by.\"\n                    },\n                    {\n                        \"name\": \"order\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"enum\": [\n                                \"asc\",\n                                \"desc\"\n                            ]\n                        },\n                        \"description\": \"An order direction.\"\n                    },\n                    {\n                        \"name\": \"textFilter\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A text filter query. Wildcard (*) is supported.\"\n                    },\n                    {\n                        \"name\": \"boolFilterList\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"onlyMy\"\n                                ]\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Bool filters.\"\n                    },\n                    {\n                        \"name\": \"attributeSelect\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"type\": \"string\",\n                                \"enum\": [\n                                    \"name\",\n                                    \"rolesIds\",\n                                    \"rolesNames\",\n                                    \"positionList\",\n                                    \"userRole\",\n                                    \"layoutSetId\",\n                                    \"layoutSetName\",\n                                    \"workingTimeCalendarId\",\n                                    \"workingTimeCalendarName\",\n                                    \"createdAt\",\n                                    \"modifiedAt\"\n                                ]\n                            }\n                        },\n                        \"style\": \"form\",\n                        \"explode\": false,\n                        \"description\": \"Attributes to return. Select only the necessary ones to improve performance.\"\n                    },\n                    {\n                        \"name\": \"whereGroup\",\n                        \"in\": \"query\",\n                        \"schema\": {\n                            \"type\": \"array\",\n                            \"items\": {\n                                \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                            }\n                        },\n                        \"style\": \"deepObject\",\n                        \"explode\": true,\n                        \"description\": \"Where items.\"\n                    }\n                ],\n                \"summary\": \"List User . teams\",\n                \"description\": \"List 'Team' records related through the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"content\": {\n                            \"application\\/json\": {\n                                \"schema\": {\n                                    \"type\": \"object\",\n                                    \"properties\": {\n                                        \"list\": {\n                                            \"type\": \"array\",\n                                            \"items\": {\n                                                \"$ref\": \"#\\/components\\/schemas\\/Team\"\n                                            },\n                                            \"description\": \"Records.\"\n                                        },\n                                        \"total\": {\n                                            \"type\": \"number\",\n                                            \"description\": \"The total number of records. If the total number is disabled, special values are returned: -1 – there are more records to paginate, -2 – there are no more records.\"\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Relate User . teams\",\n                \"description\": \"Relate 'Team' record though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"tags\": [\n                    \"User\"\n                ],\n                \"requestBody\": {\n                    \"content\": {\n                        \"application\\/json\": {\n                            \"schema\": {\n                                \"type\": \"object\",\n                                \"properties\": {\n                                    \"id\": {\n                                        \"type\": \"string\",\n                                        \"description\": \"An ID of Team record.\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                },\n                \"summary\": \"Unrelate User . teams\",\n                \"description\": \"Unrelate 'Team' record related though the 'teams' link.\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Success.\"\n                    },\n                    \"400\": {\n                        \"description\": \"Bad request. Might be a validation error. Check logs for details.\"\n                    },\n                    \"403\": {\n                        \"description\": \"Forbidden. Might be an access control error. Check logs for details.\"\n                    }\n                }\n            }\n        }\n    },\n    \"components\": {\n        \"schemas\": {\n            \"Account\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 249,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"website\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"emailAddress\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A primary email address.\"\n                    },\n                    \"emailAddressData\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"emailAddress\": {\n                                    \"type\": \"string\"\n                                },\n                                \"primary\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"optOut\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"invalid\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"lower\": {\n                                    \"type\": \"string\",\n                                    \"readOnly\": true\n                                }\n                            },\n                            \"required\": [\n                                \"emailAddress\",\n                                \"primary\"\n                            ]\n                        },\n                        \"description\": \"Multiple email addresses\"\n                    },\n                    \"phoneNumber\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 36,\n                        \"readOnly\": false,\n                        \"description\": \"A primary phone number.\"\n                    },\n                    \"phoneNumberData\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"phoneNumber\": {\n                                    \"type\": \"string\"\n                                },\n                                \"primary\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"optOut\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"invalid\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"type\": {\n                                    \"type\": \"string\",\n                                    \"enum\": [\n                                        \"Office\",\n                                        \"Mobile\",\n                                        \"Fax\",\n                                        \"Other\"\n                                    ]\n                                }\n                            },\n                            \"required\": [\n                                \"phoneNumber\",\n                                \"primary\"\n                            ]\n                        },\n                        \"description\": \"Multiple phone numbers.\"\n                    },\n                    \"type\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Customer\",\n                            \"Investor\",\n                            \"Partner\",\n                            \"Reseller\"\n                        ]\n                    },\n                    \"industry\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Advertising\",\n                            \"Aerospace\",\n                            \"Agriculture\",\n                            \"Apparel & Accessories\",\n                            \"Architecture\",\n                            \"Automotive\",\n                            \"Banking\",\n                            \"Biotechnology\",\n                            \"Building Materials & Equipment\",\n                            \"Chemical\",\n                            \"Construction\",\n                            \"Consulting\",\n                            \"Computer\",\n                            \"Culture\",\n                            \"Creative\",\n                            \"Defense\",\n                            \"Education\",\n                            \"Electronics\",\n                            \"Electric Power\",\n                            \"Energy\",\n                            \"Entertainment & Leisure\",\n                            \"Finance\",\n                            \"Food & Beverage\",\n                            \"Grocery\",\n                            \"Healthcare\",\n                            \"Hospitality\",\n                            \"Insurance\",\n                            \"Legal\",\n                            \"Manufacturing\",\n                            \"Mass Media\",\n                            \"Marketing\",\n                            \"Mining\",\n                            \"Music\",\n                            \"Publishing\",\n                            \"Petroleum\",\n                            \"Real Estate\",\n                            \"Retail\",\n                            \"Service\",\n                            \"Sports\",\n                            \"Software\",\n                            \"Support\",\n                            \"Shipping\",\n                            \"Travel\",\n                            \"Technology\",\n                            \"Telecommunications\",\n                            \"Television\",\n                            \"Transportation\",\n                            \"Testing, Inspection & Certification\",\n                            \"Venture Capital\",\n                            \"Wholesale\",\n                            \"Water\"\n                        ]\n                    },\n                    \"sicCode\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 40,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"billingAddressStreet\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"billingAddressCity\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"billingAddressState\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"billingAddressCountry\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"billingAddressPostalCode\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 40,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"shippingAddressStreet\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"shippingAddressCity\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"shippingAddressState\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"shippingAddressCountry\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"shippingAddressPostalCode\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 40,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"campaignId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Campaign type.\"\n                    },\n                    \"campaignName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"targetListsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the TargetList type.\"\n                    },\n                    \"targetListsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"targetListId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false\n                    },\n                    \"targetListName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"originalLeadId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Lead type.\"\n                    },\n                    \"originalLeadName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"emailAddressIsOptedOut\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"emailAddressIsInvalid\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"phoneNumberIsOptedOut\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"phoneNumberIsInvalid\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"streamUpdatedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    }\n                }\n            },\n            \"Account_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Account\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\"\n                ]\n            },\n            \"Call\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Planned\",\n                            \"Held\",\n                            \"Not Held\"\n                        ]\n                    },\n                    \"dateStart\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"dateEnd\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"direction\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Outbound\",\n                            \"Inbound\"\n                        ]\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"parentId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A foreign record ID.\"\n                    },\n                    \"parentType\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Account\",\n                            \"Lead\",\n                            \"Contact\",\n                            \"Opportunity\",\n                            \"Case\",\n                            \"CCompany\"\n                        ],\n                        \"description\": \"An entity type.\"\n                    },\n                    \"parentName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"accountId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Account type.\"\n                    },\n                    \"accountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"uid\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"acceptanceStatus\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"None\",\n                            \"Accepted\",\n                            \"Tentative\",\n                            \"Declined\"\n                        ]\n                    },\n                    \"usersIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the User type.\"\n                    },\n                    \"usersNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"usersColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"status\": {\n                                    \"type\": \"string\"\n                                }\n                            }\n                        }\n                    },\n                    \"contactsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Contact type.\"\n                    },\n                    \"contactsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"contactsColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"status\": {\n                                    \"type\": \"string\"\n                                }\n                            }\n                        }\n                    },\n                    \"leadsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Lead type.\"\n                    },\n                    \"leadsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"leadsColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"status\": {\n                                    \"type\": \"string\"\n                                }\n                            }\n                        }\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    }\n                }\n            },\n            \"Call_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Call\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\",\n                    \"dateStart\",\n                    \"dateEnd\",\n                    \"assignedUserId\"\n                ]\n            },\n            \"Campaign\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Planning\",\n                            \"Active\",\n                            \"Inactive\",\n                            \"Complete\"\n                        ]\n                    },\n                    \"type\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Email\",\n                            \"Newsletter\",\n                            \"Informational Email\",\n                            \"Web\",\n                            \"Television\",\n                            \"Radio\",\n                            \"Mail\"\n                        ]\n                    },\n                    \"startDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"format\": \"date\",\n                        \"description\": \"A date.\"\n                    },\n                    \"endDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"format\": \"date\",\n                        \"description\": \"A date.\"\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"targetListsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the TargetList type.\"\n                    },\n                    \"targetListsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"excludingTargetListsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the TargetList type.\"\n                    },\n                    \"excludingTargetListsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"sentCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"openedCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"clickedCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"optedInCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"optedOutCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"bouncedCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"hardBouncedCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"softBouncedCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"leadCreatedCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"revenue\": {\n                        \"readOnly\": true,\n                        \"type\": [\n                            \"number\",\n                            \"null\"\n                        ],\n                        \"description\": \"A currency amount.\"\n                    },\n                    \"revenueCurrency\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"enum\": [\n                            \"USD\",\n                            \"EUR\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A code.\"\n                    },\n                    \"budget\": {\n                        \"readOnly\": false,\n                        \"type\": [\n                            \"number\",\n                            \"null\"\n                        ],\n                        \"description\": \"A currency amount.\"\n                    },\n                    \"budgetCurrency\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"enum\": [\n                            \"USD\",\n                            \"EUR\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A code.\"\n                    },\n                    \"contactsTemplateId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Template type.\"\n                    },\n                    \"contactsTemplateName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"leadsTemplateId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Template type.\"\n                    },\n                    \"leadsTemplateName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"accountsTemplateId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Template type.\"\n                    },\n                    \"accountsTemplateName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"usersTemplateId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Template type.\"\n                    },\n                    \"usersTemplateName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"mailMergeOnlyWithAddress\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"revenueConverted\": {\n                        \"type\": [\n                            \"number\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A currency amount converted to the default currency.\"\n                    },\n                    \"budgetConverted\": {\n                        \"type\": [\n                            \"number\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A currency amount converted to the default currency.\"\n                    }\n                }\n            },\n            \"Campaign_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Campaign\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\"\n                ]\n            },\n            \"Case\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"number\": {\n                        \"type\": \"integer\",\n                        \"readOnly\": true,\n                        \"description\": \"An auto-increment number.\"\n                    },\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"New\",\n                            \"Assigned\",\n                            \"Pending\",\n                            \"Closed\",\n                            \"Rejected\",\n                            \"Duplicate\"\n                        ]\n                    },\n                    \"priority\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Low\",\n                            \"Normal\",\n                            \"High\",\n                            \"Urgent\"\n                        ]\n                    },\n                    \"type\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Question\",\n                            \"Incident\",\n                            \"Problem\"\n                        ]\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"accountId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Account type.\"\n                    },\n                    \"accountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"leadId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Lead type.\"\n                    },\n                    \"leadName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"contactId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Contact type.\"\n                    },\n                    \"contactName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"contactsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Contact type.\"\n                    },\n                    \"contactsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"inboundEmailId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the InboundEmail type.\"\n                    },\n                    \"inboundEmailName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"originalEmailId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false\n                    },\n                    \"originalEmailName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"isInternal\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"collaboratorsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the User type.\"\n                    },\n                    \"collaboratorsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"streamUpdatedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    }\n                }\n            },\n            \"Case_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Case\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\"\n                ]\n            },\n            \"Contact\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"salutationName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Mr.\",\n                            \"Ms.\",\n                            \"Mrs.\",\n                            \"Dr.\"\n                        ]\n                    },\n                    \"firstName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"lastName\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"title\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"emailAddress\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A primary email address.\"\n                    },\n                    \"emailAddressData\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"emailAddress\": {\n                                    \"type\": \"string\"\n                                },\n                                \"primary\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"optOut\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"invalid\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"lower\": {\n                                    \"type\": \"string\",\n                                    \"readOnly\": true\n                                }\n                            },\n                            \"required\": [\n                                \"emailAddress\",\n                                \"primary\"\n                            ]\n                        },\n                        \"description\": \"Multiple email addresses\"\n                    },\n                    \"phoneNumber\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 36,\n                        \"readOnly\": false,\n                        \"description\": \"A primary phone number.\"\n                    },\n                    \"phoneNumberData\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"phoneNumber\": {\n                                    \"type\": \"string\"\n                                },\n                                \"primary\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"optOut\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"invalid\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"type\": {\n                                    \"type\": \"string\",\n                                    \"enum\": [\n                                        \"Mobile\",\n                                        \"Office\",\n                                        \"Home\",\n                                        \"Fax\",\n                                        \"Other\"\n                                    ]\n                                }\n                            },\n                            \"required\": [\n                                \"phoneNumber\",\n                                \"primary\"\n                            ]\n                        },\n                        \"description\": \"Multiple phone numbers.\"\n                    },\n                    \"doNotCall\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"addressStreet\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"addressCity\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"addressState\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"addressCountry\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"addressPostalCode\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 40,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"accountId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Account type.\"\n                    },\n                    \"accountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"accountsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Account type.\"\n                    },\n                    \"accountsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"accountsColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"role\": {\n                                    \"type\": \"string\",\n                                    \"maxLength\": 100\n                                },\n                                \"isInactive\": {\n                                    \"type\": \"boolean\"\n                                }\n                            }\n                        }\n                    },\n                    \"accountRole\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"accountIsInactive\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"accountType\": {\n                        \"readOnly\": true,\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ]\n                    },\n                    \"opportunityRole\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Decision Maker\",\n                            \"Evaluator\",\n                            \"Influencer\"\n                        ]\n                    },\n                    \"acceptanceStatusMeetings\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false\n                    },\n                    \"acceptanceStatusCalls\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false\n                    },\n                    \"campaignId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Campaign type.\"\n                    },\n                    \"campaignName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"targetListsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the TargetList type.\"\n                    },\n                    \"targetListsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"targetListId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false\n                    },\n                    \"targetListName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"portalUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"portalUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"hasPortalUser\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"originalLeadId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Lead type.\"\n                    },\n                    \"originalLeadName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"originalEmailId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false\n                    },\n                    \"originalEmailName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"middleName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"emailAddressIsOptedOut\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"emailAddressIsInvalid\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"phoneNumberIsOptedOut\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"phoneNumberIsInvalid\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"streamUpdatedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    }\n                }\n            },\n            \"Contact_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Contact\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"lastName\"\n                ]\n            },\n            \"Document\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"fileId\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Attachment type.\"\n                    },\n                    \"fileName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Draft\",\n                            \"Active\",\n                            \"Canceled\",\n                            \"Expired\"\n                        ]\n                    },\n                    \"type\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Contract\",\n                            \"NDA\",\n                            \"EULA\",\n                            \"License Agreement\"\n                        ]\n                    },\n                    \"publishDate\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"format\": \"date\",\n                        \"description\": \"A date.\"\n                    },\n                    \"expirationDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"format\": \"date\",\n                        \"description\": \"A date.\"\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"accountsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Account type.\"\n                    },\n                    \"accountsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"folderId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the DocumentFolder type.\"\n                    },\n                    \"folderName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    }\n                }\n            },\n            \"Document_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Document\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\",\n                    \"fileId\",\n                    \"publishDate\"\n                ]\n            },\n            \"Email\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"subject\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"fromName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"fromAddress\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"fromString\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"replyToString\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"replyToName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"replyToAddress\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"from\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"to\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"cc\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"bcc\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"replyTo\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"personStringData\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"isRead\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"isNotRead\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"isReplied\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"isNotReplied\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"isImportant\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"inTrash\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"inArchive\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"folderId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"isUsers\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"folderName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"folderStringId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"folderStringName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"messageId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"messageIdInternal\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 300,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"emailAddress\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"fromEmailAddressId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the EmailAddress type.\"\n                    },\n                    \"fromEmailAddressName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"toEmailAddressesIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the EmailAddress type.\"\n                    },\n                    \"toEmailAddressesNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"ccEmailAddressesIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the EmailAddress type.\"\n                    },\n                    \"ccEmailAddressesNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"bccEmailAddressesIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the EmailAddress type.\"\n                    },\n                    \"bccEmailAddressesNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"replyToEmailAddressesIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the EmailAddress type.\"\n                    },\n                    \"replyToEmailAddressesNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"bodyPlain\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"body\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"isHtml\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Draft\",\n                            \"Sending\",\n                            \"Sent\",\n                            \"Archived\",\n                            \"Failed\"\n                        ]\n                    },\n                    \"hasAttachment\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"parentId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A foreign record ID.\"\n                    },\n                    \"parentType\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Account\",\n                            \"Lead\",\n                            \"Contact\",\n                            \"Opportunity\",\n                            \"Case\",\n                            \"CCompany\"\n                        ],\n                        \"description\": \"An entity type.\"\n                    },\n                    \"parentName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"dateSent\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"deliveryDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"sendAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"isAutoReply\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"sentById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"sentByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"repliedId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Email type.\"\n                    },\n                    \"repliedName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"repliesIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the Email type.\"\n                    },\n                    \"repliesNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"repliesColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"status\": {\n                                    \"type\": \"string\",\n                                    \"enum\": [\n                                        \"Draft\",\n                                        \"Sending\",\n                                        \"Sent\",\n                                        \"Archived\",\n                                        \"Failed\"\n                                    ]\n                                }\n                            }\n                        }\n                    },\n                    \"isSystem\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"usersIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the User type.\"\n                    },\n                    \"usersNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"usersColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"inTrash\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"folderId\": {\n                                    \"type\": \"string\"\n                                },\n                                \"inArchive\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"isRead\": {\n                                    \"type\": \"boolean\"\n                                }\n                            }\n                        }\n                    },\n                    \"assignedUsersIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the User type.\"\n                    },\n                    \"assignedUsersNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"inboundEmailsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the InboundEmail type.\"\n                    },\n                    \"inboundEmailsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"emailAccountsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the EmailAccount type.\"\n                    },\n                    \"emailAccountsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"icsContents\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"icsEventUid\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"icsEventDateStart\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"Specified if the 'icsEventDateStart' field is all-day.\"\n                    },\n                    \"icsEventDateStartDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"format\": \"date\",\n                        \"readOnly\": true\n                    },\n                    \"createdEventId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record ID.\"\n                    },\n                    \"createdEventType\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An entity type.\"\n                    },\n                    \"createdEventName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"groupFolderId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the GroupEmailFolder type.\"\n                    },\n                    \"groupFolderName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"groupStatusFolder\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"enum\": [\n                            \"Archive\",\n                            \"Trash\"\n                        ]\n                    },\n                    \"accountId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Account type.\"\n                    },\n                    \"accountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"tasksIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the Task type.\"\n                    },\n                    \"tasksNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"tasksColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"status\": {\n                                    \"type\": \"string\",\n                                    \"enum\": [\n                                        \"Not Started\",\n                                        \"Started\",\n                                        \"Completed\",\n                                        \"Canceled\",\n                                        \"Deferred\"\n                                    ]\n                                }\n                            }\n                        }\n                    }\n                }\n            },\n            \"Email_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Email\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\",\n                    \"subject\",\n                    \"from\",\n                    \"to\"\n                ]\n            },\n            \"KnowledgeBaseArticle\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Draft\",\n                            \"In Review\",\n                            \"Published\",\n                            \"Archived\"\n                        ]\n                    },\n                    \"language\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false\n                    },\n                    \"type\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Article\"\n                        ]\n                    },\n                    \"portalsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Portal type.\"\n                    },\n                    \"portalsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"publishDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"format\": \"date\",\n                        \"description\": \"A date.\"\n                    },\n                    \"expirationDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"format\": \"date\",\n                        \"description\": \"A date.\"\n                    },\n                    \"order\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"categoriesIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the KnowledgeBaseCategory type.\"\n                    },\n                    \"categoriesNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"body\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"bodyPlain\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A multi-line text.\"\n                    }\n                }\n            },\n            \"KnowledgeBaseArticle_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/KnowledgeBaseArticle\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\"\n                ]\n            },\n            \"Lead\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"salutationName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Mr.\",\n                            \"Ms.\",\n                            \"Mrs.\",\n                            \"Dr.\"\n                        ]\n                    },\n                    \"firstName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"lastName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"title\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"New\",\n                            \"Assigned\",\n                            \"In Process\",\n                            \"Converted\",\n                            \"Recycled\",\n                            \"Dead\"\n                        ]\n                    },\n                    \"source\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Call\",\n                            \"Email\",\n                            \"Existing Customer\",\n                            \"Partner\",\n                            \"Public Relations\",\n                            \"Web Site\",\n                            \"Campaign\",\n                            \"Other\"\n                        ]\n                    },\n                    \"industry\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Advertising\",\n                            \"Aerospace\",\n                            \"Agriculture\",\n                            \"Apparel & Accessories\",\n                            \"Architecture\",\n                            \"Automotive\",\n                            \"Banking\",\n                            \"Biotechnology\",\n                            \"Building Materials & Equipment\",\n                            \"Chemical\",\n                            \"Construction\",\n                            \"Consulting\",\n                            \"Computer\",\n                            \"Culture\",\n                            \"Creative\",\n                            \"Defense\",\n                            \"Education\",\n                            \"Electronics\",\n                            \"Electric Power\",\n                            \"Energy\",\n                            \"Entertainment & Leisure\",\n                            \"Finance\",\n                            \"Food & Beverage\",\n                            \"Grocery\",\n                            \"Healthcare\",\n                            \"Hospitality\",\n                            \"Insurance\",\n                            \"Legal\",\n                            \"Manufacturing\",\n                            \"Mass Media\",\n                            \"Marketing\",\n                            \"Mining\",\n                            \"Music\",\n                            \"Publishing\",\n                            \"Petroleum\",\n                            \"Real Estate\",\n                            \"Retail\",\n                            \"Service\",\n                            \"Sports\",\n                            \"Software\",\n                            \"Support\",\n                            \"Shipping\",\n                            \"Travel\",\n                            \"Technology\",\n                            \"Telecommunications\",\n                            \"Television\",\n                            \"Transportation\",\n                            \"Testing, Inspection & Certification\",\n                            \"Venture Capital\",\n                            \"Wholesale\",\n                            \"Water\"\n                        ]\n                    },\n                    \"opportunityAmount\": {\n                        \"readOnly\": false,\n                        \"type\": [\n                            \"number\",\n                            \"null\"\n                        ],\n                        \"minimum\": 0,\n                        \"description\": \"A currency amount.\"\n                    },\n                    \"opportunityAmountCurrency\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"enum\": [\n                            \"USD\",\n                            \"EUR\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A code.\"\n                    },\n                    \"opportunityAmountConverted\": {\n                        \"type\": [\n                            \"number\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A currency amount converted to the default currency.\"\n                    },\n                    \"website\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"addressStreet\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"addressCity\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"addressState\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"addressCountry\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"addressPostalCode\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 40,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"emailAddress\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A primary email address.\"\n                    },\n                    \"emailAddressData\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"emailAddress\": {\n                                    \"type\": \"string\"\n                                },\n                                \"primary\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"optOut\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"invalid\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"lower\": {\n                                    \"type\": \"string\",\n                                    \"readOnly\": true\n                                }\n                            },\n                            \"required\": [\n                                \"emailAddress\",\n                                \"primary\"\n                            ]\n                        },\n                        \"description\": \"Multiple email addresses\"\n                    },\n                    \"phoneNumber\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 36,\n                        \"readOnly\": false,\n                        \"description\": \"A primary phone number.\"\n                    },\n                    \"phoneNumberData\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"phoneNumber\": {\n                                    \"type\": \"string\"\n                                },\n                                \"primary\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"optOut\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"invalid\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"type\": {\n                                    \"type\": \"string\",\n                                    \"enum\": [\n                                        \"Mobile\",\n                                        \"Office\",\n                                        \"Home\",\n                                        \"Fax\",\n                                        \"Other\"\n                                    ]\n                                }\n                            },\n                            \"required\": [\n                                \"phoneNumber\",\n                                \"primary\"\n                            ]\n                        },\n                        \"description\": \"Multiple phone numbers.\"\n                    },\n                    \"doNotCall\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"convertedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"accountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"acceptanceStatusMeetings\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false\n                    },\n                    \"acceptanceStatusCalls\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"campaignId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Campaign type.\"\n                    },\n                    \"campaignName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"createdAccountId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Account type.\"\n                    },\n                    \"createdAccountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"createdContactId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Contact type.\"\n                    },\n                    \"createdContactName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"createdOpportunityId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Opportunity type.\"\n                    },\n                    \"createdOpportunityName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"targetListsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the TargetList type.\"\n                    },\n                    \"targetListsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"targetListId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false\n                    },\n                    \"targetListName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"originalEmailId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false\n                    },\n                    \"originalEmailName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"middleName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"emailAddressIsOptedOut\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"emailAddressIsInvalid\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"phoneNumberIsOptedOut\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"phoneNumberIsInvalid\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"streamUpdatedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    }\n                }\n            },\n            \"Lead_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Lead\",\n                \"type\": \"object\"\n            },\n            \"Meeting\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Planned\",\n                            \"Held\",\n                            \"Not Held\"\n                        ]\n                    },\n                    \"dateStart\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"Specified if the 'dateStart' field is all-day.\"\n                    },\n                    \"dateStartDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"format\": \"date\",\n                        \"readOnly\": false\n                    },\n                    \"dateEnd\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"Specified if the 'dateEnd' field is all-day.\"\n                    },\n                    \"dateEndDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"format\": \"date\",\n                        \"readOnly\": false\n                    },\n                    \"isAllDay\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"parentId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A foreign record ID.\"\n                    },\n                    \"parentType\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Account\",\n                            \"Lead\",\n                            \"Contact\",\n                            \"Opportunity\",\n                            \"Case\",\n                            \"CCompany\"\n                        ],\n                        \"description\": \"An entity type.\"\n                    },\n                    \"parentName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"accountId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Account type.\"\n                    },\n                    \"accountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"uid\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"joinUrl\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 320,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"acceptanceStatus\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"None\",\n                            \"Accepted\",\n                            \"Tentative\",\n                            \"Declined\"\n                        ]\n                    },\n                    \"usersIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the User type.\"\n                    },\n                    \"usersNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"usersColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"status\": {\n                                    \"type\": \"string\"\n                                }\n                            }\n                        }\n                    },\n                    \"contactsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Contact type.\"\n                    },\n                    \"contactsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"contactsColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"status\": {\n                                    \"type\": \"string\"\n                                }\n                            }\n                        }\n                    },\n                    \"leadsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Lead type.\"\n                    },\n                    \"leadsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"leadsColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"status\": {\n                                    \"type\": \"string\"\n                                }\n                            }\n                        }\n                    },\n                    \"sourceEmailId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false\n                    },\n                    \"sourceEmailName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"streamUpdatedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    }\n                }\n            },\n            \"Meeting_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Meeting\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\",\n                    \"dateStart\",\n                    \"dateEnd\",\n                    \"assignedUserId\"\n                ]\n            },\n            \"Opportunity\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"amount\": {\n                        \"readOnly\": false,\n                        \"type\": \"number\",\n                        \"minimum\": 0,\n                        \"description\": \"A currency amount.\"\n                    },\n                    \"amountCurrency\": {\n                        \"type\": \"string\",\n                        \"enum\": [\n                            \"USD\",\n                            \"EUR\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A code.\"\n                    },\n                    \"amountConverted\": {\n                        \"type\": [\n                            \"number\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A currency amount converted to the default currency.\"\n                    },\n                    \"amountWeightedConverted\": {\n                        \"type\": [\n                            \"number\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"accountId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Account type.\"\n                    },\n                    \"accountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"contactsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Contact type.\"\n                    },\n                    \"contactsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"contactsColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"role\": {\n                                    \"type\": [\n                                        \"string\",\n                                        \"null\"\n                                    ],\n                                    \"enum\": [\n                                        \"Decision Maker\",\n                                        \"Evaluator\",\n                                        \"Influencer\"\n                                    ]\n                                }\n                            }\n                        }\n                    },\n                    \"contactId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Contact type.\"\n                    },\n                    \"contactName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"stage\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Prospecting\",\n                            \"Qualification\",\n                            \"Proposal\",\n                            \"Negotiation\",\n                            \"Closed Won\",\n                            \"Closed Lost\"\n                        ]\n                    },\n                    \"lastStage\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false\n                    },\n                    \"probability\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"minimum\": 0,\n                        \"maximum\": 100\n                    },\n                    \"leadSource\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Call\",\n                            \"Email\",\n                            \"Existing Customer\",\n                            \"Partner\",\n                            \"Public Relations\",\n                            \"Web Site\",\n                            \"Campaign\",\n                            \"Other\"\n                        ]\n                    },\n                    \"closeDate\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"format\": \"date\",\n                        \"description\": \"A date.\"\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"campaignId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Campaign type.\"\n                    },\n                    \"campaignName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"originalLeadId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Lead type.\"\n                    },\n                    \"originalLeadName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"contactRole\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Decision Maker\",\n                            \"Evaluator\",\n                            \"Influencer\"\n                        ]\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"streamUpdatedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    }\n                }\n            },\n            \"Opportunity_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Opportunity\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\",\n                    \"amount\",\n                    \"amountCurrency\",\n                    \"closeDate\"\n                ]\n            },\n            \"TargetList\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"categoryId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the TargetListCategory type.\"\n                    },\n                    \"categoryName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"entryCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"optedOutCount\": {\n                        \"type\": [\n                            \"integer\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"sourceCampaignId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false\n                    },\n                    \"sourceCampaignName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"targetStatus\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"enum\": [\n                            \"Listed\",\n                            \"Opted Out\"\n                        ]\n                    },\n                    \"isOptedOut\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    }\n                }\n            },\n            \"TargetList_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/TargetList\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\"\n                ]\n            },\n            \"Task\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 255,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Not Started\",\n                            \"Started\",\n                            \"Completed\",\n                            \"Canceled\",\n                            \"Deferred\"\n                        ]\n                    },\n                    \"priority\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Low\",\n                            \"Normal\",\n                            \"High\",\n                            \"Urgent\"\n                        ]\n                    },\n                    \"dateStart\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"Specified if the 'dateStart' field is all-day.\"\n                    },\n                    \"dateStartDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"format\": \"date\",\n                        \"readOnly\": false\n                    },\n                    \"dateEnd\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"Specified if the 'dateEnd' field is all-day.\"\n                    },\n                    \"dateEndDate\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"format\": \"date\",\n                        \"readOnly\": false\n                    },\n                    \"dateCompleted\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"description\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A multi-line text.\"\n                    },\n                    \"parentId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"A foreign record ID.\"\n                    },\n                    \"parentType\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Account\",\n                            \"Contact\",\n                            \"Lead\",\n                            \"Opportunity\",\n                            \"Case\",\n                            \"CCompany\"\n                        ],\n                        \"description\": \"An entity type.\"\n                    },\n                    \"parentName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"accountId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Account type.\"\n                    },\n                    \"accountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"contactId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Contact type.\"\n                    },\n                    \"contactName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"modifiedById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"modifiedByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"assignedUserId\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"assignedUserName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"collaboratorsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the User type.\"\n                    },\n                    \"collaboratorsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"streamUpdatedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    }\n                }\n            },\n            \"Task_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Task\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"name\",\n                    \"assignedUserId\"\n                ]\n            },\n            \"Team\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"name\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"rolesIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": false,\n                        \"description\": \"IDs of records of the Role type.\"\n                    },\n                    \"rolesNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"positionList\": {\n                        \"type\": \"array\",\n                        \"readOnly\": false,\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"description\": \"A multi-enum.\"\n                    },\n                    \"layoutSetId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the LayoutSet type.\"\n                    },\n                    \"layoutSetName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"workingTimeCalendarId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the WorkingTimeCalendar type.\"\n                    },\n                    \"workingTimeCalendarName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    }\n                }\n            },\n            \"Team_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/Team\",\n                \"type\": \"object\"\n            },\n            \"User\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"description\": \"An ID.\"\n                    },\n                    \"userName\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 50,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"type\": {\n                        \"type\": \"string\",\n                        \"readOnly\": true,\n                        \"enum\": [\n                            \"regular\",\n                            \"admin\",\n                            \"portal\",\n                            \"system\",\n                            \"super-admin\",\n                            \"api\"\n                        ]\n                    },\n                    \"authMethod\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"enum\": [\n                            \"ApiKey\",\n                            \"Hmac\"\n                        ]\n                    },\n                    \"apiKey\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"secretKey\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"salutationName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Mr.\",\n                            \"Ms.\",\n                            \"Mrs.\",\n                            \"Dr.\"\n                        ]\n                    },\n                    \"firstName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"lastName\": {\n                        \"type\": \"string\",\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"isActive\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": true\n                    },\n                    \"title\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"position\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": true,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"emailAddress\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 255,\n                        \"readOnly\": true,\n                        \"description\": \"A primary email address.\"\n                    },\n                    \"emailAddressData\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"emailAddress\": {\n                                    \"type\": \"string\"\n                                },\n                                \"primary\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"optOut\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"invalid\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"lower\": {\n                                    \"type\": \"string\",\n                                    \"readOnly\": true\n                                }\n                            },\n                            \"required\": [\n                                \"emailAddress\",\n                                \"primary\"\n                            ]\n                        },\n                        \"description\": \"Multiple email addresses\",\n                        \"readOnly\": true\n                    },\n                    \"phoneNumber\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 36,\n                        \"readOnly\": false,\n                        \"description\": \"A primary phone number.\"\n                    },\n                    \"phoneNumberData\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"phoneNumber\": {\n                                    \"type\": \"string\"\n                                },\n                                \"primary\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"optOut\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"invalid\": {\n                                    \"type\": \"boolean\"\n                                },\n                                \"type\": {\n                                    \"type\": \"string\",\n                                    \"enum\": [\n                                        \"Mobile\",\n                                        \"Office\",\n                                        \"Home\",\n                                        \"Fax\",\n                                        \"Other\"\n                                    ]\n                                }\n                            },\n                            \"required\": [\n                                \"phoneNumber\",\n                                \"primary\"\n                            ]\n                        },\n                        \"description\": \"Multiple phone numbers.\"\n                    },\n                    \"defaultTeamId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Team type.\"\n                    },\n                    \"defaultTeamName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"acceptanceStatusMeetings\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false\n                    },\n                    \"acceptanceStatusCalls\": {\n                        \"type\": \"string\",\n                        \"readOnly\": false\n                    },\n                    \"teamsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the Team type.\"\n                    },\n                    \"teamsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"teamsColumns\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => object} map. Relationship column values.\",\n                        \"additionalProperties\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"role\": {\n                                    \"type\": \"string\"\n                                }\n                            }\n                        }\n                    },\n                    \"rolesIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the Role type.\"\n                    },\n                    \"rolesNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"portalsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the Portal type.\"\n                    },\n                    \"portalsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"portalRolesIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the PortalRole type.\"\n                    },\n                    \"portalRolesNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"contactId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the Contact type.\"\n                    },\n                    \"contactName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"accountsIds\": {\n                        \"type\": [\n                            \"array\",\n                            \"null\"\n                        ],\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"IDs of records of the Account type.\"\n                    },\n                    \"accountsNames\": {\n                        \"type\": [\n                            \"object\",\n                            \"null\"\n                        ],\n                        \"additionalProperties\": {\n                            \"type\": \"string\"\n                        },\n                        \"readOnly\": true,\n                        \"description\": \"An {ID => record name} map.\"\n                    },\n                    \"accountId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true\n                    },\n                    \"accountName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"avatarId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the Attachment type.\"\n                    },\n                    \"avatarName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"gender\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"enum\": [\n                            \"Male\",\n                            \"Female\",\n                            \"Neutral\"\n                        ]\n                    },\n                    \"createdAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"modifiedAt\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"createdById\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the User type.\"\n                    },\n                    \"createdByName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"dashboardTemplateId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": false,\n                        \"description\": \"An ID of the record of the DashboardTemplate type.\"\n                    },\n                    \"dashboardTemplateName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"workingTimeCalendarId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the WorkingTimeCalendar type.\"\n                    },\n                    \"workingTimeCalendarName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"layoutSetId\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"An ID of the record of the LayoutSet type.\"\n                    },\n                    \"layoutSetName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"description\": \"A foreign record name.\"\n                    },\n                    \"lastAccess\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"readOnly\": true,\n                        \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2}$\",\n                        \"examples\": [\n                            \"2026-11-29 12:34:56\"\n                        ],\n                        \"description\": \"A timestamp in UTC.\"\n                    },\n                    \"middleName\": {\n                        \"type\": [\n                            \"string\",\n                            \"null\"\n                        ],\n                        \"maxLength\": 100,\n                        \"readOnly\": false,\n                        \"description\": \"A one-line string.\"\n                    },\n                    \"emailAddressIsOptedOut\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"emailAddressIsInvalid\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"phoneNumberIsOptedOut\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    },\n                    \"phoneNumberIsInvalid\": {\n                        \"type\": \"boolean\",\n                        \"readOnly\": false\n                    }\n                }\n            },\n            \"User_create\": {\n                \"$ref\": \"#\\/components\\/schemas\\/User\",\n                \"type\": \"object\",\n                \"required\": [\n                    \"userName\",\n                    \"lastName\"\n                ]\n            },\n            \"whereItem\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"type\": {\n                        \"type\": \"string\",\n                        \"enum\": [\n                            \"and\",\n                            \"or\",\n                            \"not\",\n                            \"subQueryNotIn\",\n                            \"subQueryIn\",\n                            \"expression\",\n                            \"in\",\n                            \"notIn\",\n                            \"equals\",\n                            \"notEquals\",\n                            \"on\",\n                            \"notOn\",\n                            \"like\",\n                            \"notLike\",\n                            \"startsWith\",\n                            \"endsWith\",\n                            \"contains\",\n                            \"notContains\",\n                            \"greaterThan\",\n                            \"lessThan\",\n                            \"greaterThanOrEquals\",\n                            \"lessThanOrEquals\",\n                            \"after\",\n                            \"before\",\n                            \"between\",\n                            \"ever\",\n                            \"any\",\n                            \"none\",\n                            \"isNull\",\n                            \"isNotNull\",\n                            \"isTrue\",\n                            \"isFalse\",\n                            \"today\",\n                            \"past\",\n                            \"future\",\n                            \"lastSevenDays\",\n                            \"lastXDays\",\n                            \"nextXDays\",\n                            \"olderThanXDays\",\n                            \"afterXDays\",\n                            \"currentMonth\",\n                            \"nextMonth\",\n                            \"lastMonth\",\n                            \"currentQuarter\",\n                            \"lastQuarter\",\n                            \"currentYear\",\n                            \"lastYear\",\n                            \"currentFiscalYear\",\n                            \"lastFiscalYear\",\n                            \"currentFiscalQuarter\",\n                            \"lastFiscalQuarter\",\n                            \"arrayAnyOf\",\n                            \"arrayNoneOf\",\n                            \"arrayAllOf\",\n                            \"arrayIsEmpty\",\n                            \"arrayIsNotEmpty\",\n                            \"linkedWith\",\n                            \"notLinkedWith\",\n                            \"linkedWithAll\",\n                            \"isLinked\",\n                            \"isNotLinked\"\n                        ],\n                        \"description\": \"An operator.\"\n                    },\n                    \"attribute\": {\n                        \"type\": \"string\",\n                        \"description\": \"An attribute or field.\"\n                    },\n                    \"value\": {\n                        \"oneOf\": [\n                            {\n                                \"type\": [\n                                    \"string\",\n                                    \"integer\",\n                                    \"number\",\n                                    \"boolean\",\n                                    \"null\"\n                                ]\n                            },\n                            {\n                                \"type\": \"array\",\n                                \"items\": {\n                                    \"$ref\": \"#\\/components\\/schemas\\/whereItem\"\n                                }\n                            },\n                            {\n                                \"type\": \"array\",\n                                \"items\": {\n                                    \"type\": \"string\"\n                                }\n                            }\n                        ],\n                        \"description\": \"A value. A scalar, or an array of strings.\"\n                    },\n                    \"dateTime\": {\n                        \"type\": \"boolean\",\n                        \"description\": \"Set true for date-time fields.\"\n                    },\n                    \"timeZone\": {\n                        \"type\": \"string\",\n                        \"description\": \"A time zone. For date-time fields.\"\n                    }\n                },\n                \"required\": [\n                    \"type\"\n                ],\n                \"description\": \"A where item.\"\n            }\n        },\n        \"securitySchemes\": {\n            \"ApiKeyAuth\": {\n                \"type\": \"apiKey\",\n                \"in\": \"header\",\n                \"name\": \"X-Api-Key\"\n            }\n        }\n    },\n    \"security\": [\n        {\n            \"ApiKeyAuth\": []\n        }\n    ],\n    \"servers\": [\n        {\n            \"url\": \"{siteUrl}\\/api\\/v1\",\n            \"variables\": {\n                \"siteUrl\": {\n                    \"default\": \"http:\\/\\/localhost\",\n                    \"description\": \"An URL of you Espo instance.\"\n                }\n            }\n        }\n    ]\n}"
  },
  {
    "path": "docs/css/extra.css",
    "content": ":root {\n    //--md-link-color: #537898;\n    --md-accent-fg-color: #af4d73;\n    --md-accent-fg-color-light: #cc95aa;\n}\n\n* {\n    animation: none !important;\n    transition: none !important;\n}\n\n.md-grid {\n    max-width: 62rem;\n}\n\n.md-typeset .admonition {\n    border-style: none;\n}\n\n.md-typeset > p > img {\n    display: block;\n    margin-left: auto;\n    margin-right: auto;\n\n    border-radius: 5px;\n    box-shadow: var(--md-shadow-z1);\n}\n\nlabel.md-nav__link:not(.md-nav__container):focus,\nlabel.md-nav__link:not(.md-nav__container):hover {\n    color: var(--md-typeset-color);\n}\n\nlabel.md-nav__link:not(.md-nav__container):hover {\n    text-decoration: underline;\n}\n\na.md-nav__link:not(.md-nav__container):hover {\n    color: var(--md-typeset-a-color);\n}\n\n.md-nav--secondary a.md-nav__link:not(.md-nav__container):hover {\n    color: var(--md-typeset-color)\n}\n\n.md-typeset h1 {\n    font-weight: 400 !important;\n    color: var(--md-default-fg-color);\n    font-size: 1.62rem;\n    border-bottom: 1px solid var(--md-default-fg-color--lightest);\n    padding-bottom: 0.14em;\n}\n.md-typeset h2 {\n    font-weight: 400 !important;\n    border-bottom: 1px solid var(--md-default-fg-color--lightest);\n    padding-bottom: 0.09em;\n}\n\n.md-main .md-nav__item .md-nav__link--active {\n    color: var(--md-accent-fg-color-light);\n}\n\n.md-main a:focus,\n.md-main a:hover,\n.md-main a:visited,\n.md-main a {\n    color: var(--md-typeset-a-color);\n}\n\n.md-main a:focus,\n.md-main a:hover {\n    text-decoration: underline !important;\n    color: var(--md-typeset-a-color);\n}\n\n.md-nav--secondary a:focus,\n.md-nav--secondary a:hover,\n.md-nav--secondary a:visited,\n.md-nav--secondary a {\n    color: var(--md-default-fg-color);\n}\n\n.md-typeset ul li,\n.md-typeset ol li {\n    margin-bottom: 0.3em;\n}\n\n.md-typeset h4 {\n    margin-top: 1.2rem;\n}\n\n.md-nav--primary .md-nav__title {\n    display: none;\n}\n\n.md-nav--primary a.md-nav__link--active {\n    pointer-events: none;\n}\n\n.md-nav--secondary > .md-nav__list > .md-nav__item > .md-nav {\n    font-size: 0.65rem;\n    //display: none;\n}\n\n.md-nav__list {\n    user-select: none;\n}\n\n.md-typeset table {\n    table-layout: fixed;\n    width: 100%;\n    font-size: .8rem;\n\n    border-collapse: collapse;\n    border-spacing: 0;\n}\n\n.md-typeset table:not([class]) {\n    display: table;\n    font-size: .8rem;\n\n    tr {\n        td, th {\n            border: .05rem solid var(--md-typeset-table-color);\n            padding: 0.6em 0.8em;\n        }\n    }\n}\n"
  },
  {
    "path": "docs/development/acl.md",
    "content": "# ACL · Access control level\n\n## Access checking\n\nThere are two [container services](di.md/#container-services) that provide the ability to check access to records, scopes and fields:\n\n* AclManager – `Espo\\Core\\AclManager` – to check access for any user; the user is passed as a method parameter;\n* Acl – `Espo\\Core\\Acl` – an *AclManager* wrapper to check access for the current user.\n\nAclManager usage examples:\n\n```php\n<?php\nuse Espo\\Core\\Acl\\Table;\n\n// Available actions: create, read, edit, delete, stream.\n\n// Check read access.\n$hasAccess = $aclManager->check($user, $entity, Table::ACTION_READ);\n\n// Check access to a scope.\n$hasAccess = $aclManager->check($user, 'Account');\n\n// Get an access level.\n$level = $aclManager->check($user, 'Account', Table::ACTION_EDIT);\n\n// Get a permission level (e.g. assignment, portal).\n$assignmentPermission = $aclManager->getPermissionLevel($user, 'assignmentPermission');\n\n// Check the user is owned of a record (through assigned user).\n$isOwner =  $aclManager->checkOwnershipOwn($user, $entity);\n\n// Check a user teams set intersects with record's teams.\n$inTeam =  $aclManager->checkOwnershipTeam($user, $entity);\n\n// Attributes/fields/links the user does not have access to.\n$attributeList = $aclManager->getScopeForbiddenAttributeList($user, 'Account', Table::ACTION_READ);\n$fieldList = $aclManager->getScopeForbiddenFieldList($user, 'Account', Table::ACTION_READ);\n$linkList = $aclManager->getScopeForbiddenLinkList($user, 'Account', Table::ACTION_READ);\n\n// Check access to a specific field.\n$hasAccess = $aclManager->checkField($user, $scope, $field, Table::ACTION_EDIT);\n```\n\nThe methods of the *Acl* service class are mostly the same as in *AclManager* but without the *$user* parameter, as the current user is used.\n\n## Custom ACL\n\n### Access checker\n\nAn access checker implements access checking against an entity instance and/or a scope name for a giver user. The *data* object is passed to checking method – this object contain role table data for the user.\n\nFor example, it check whether a user: has access to the Account, can edit Accounts, or has access to a specific Account record. \n\nYou can define a custom [access checker](metadata/acl-defs.md#accesscheckerclassname) class for a specific scope. Note that portals use a separate access checker.\n\n### Ownership checker\n\nAn ownership checker checks how the given user is related to the given entity – whether the user is an owner, the user is in the same team the record is related to, or the portal user belongs to the account the record is related to.\n\nYou can define a custom [ownership checker](metadata/acl-defs.md#ownershipcheckerclassname) class for a specific scope. Note that portals use a separate ownership access checker.\n\n### Access control filters\n\nYou may also need to define custom [access control filters](metadata/select-defs.md#accesscontrolfilterclassnamemap). These filters belong to the [Select framework](select-builder.md), not to the ACL framework.\n\nWhen the framework build a database query in order to display a record list for the user, it applies an access control filter to the query. Which exactly filter is applied – depends on the user's roles. It's also possible to customize the filter application rules with a custom [resolver](metadata/select-defs.md#accesscontrolfilterresolverclassname).\n\n"
  },
  {
    "path": "docs/development/api/account.md",
    "content": "# API · Account\n\n* [List](#list)\n* [Create](#create)\n* [Read](#read)\n* [Update](#read)\n* [Delete](#delete)\n* [Stream](#stream)\n* [Relationships](#relationships)\n\n## List\n\n### GET Account\n\nReturns a list of accounts and total number of records. It's possible to specify filters.\n\nGET parameters are available [here](crud.md#list).\n\nRequires *read* access to *Account* scope.\n\nExample:\n\n```\nGET Account?select=name&maxSize=2&orderBy=name&order=asc\n```\n\nwill return:\n\n```json\n{\n    \"list\": [\n        {\n            \"id\": \"someId1\",\n            \"name\": \"Test 1\"\n        },\n        {\n            \"id\": \"someId2\",\n            \"name\": \"Test 2\"\n        }\n    ],\n    \"total\": 2100\n}\n```\n\n## Create\n\n### POST Account\n\nCreates an account. Returns its attributes.\n\nRequires *create* access to *Account* scope.\n\nPayload: Record [attributes](../../administration/terms-and-naming.md#attribute).\n\nExample:\n\n```\nPOST Account\n```\n\nwith payload:\n\n```json\n{\n    \"name\": \"Test\",\n    \"assignedUserId\": \"someUserId\"\n}\n```\n\n## Read\n\n### GET Account/{id}\n\nReturns [attributes](../../administration/terms-and-naming.md#attribute) of a specific Account record.\n\nRequires *read* access to Account record.\n\n\nExample:\n\n```\nGET Account/someId\n```\n\nwith return:\n\n```json\n{\n    \"id\": \"someId\",\n    \"name\": \"Test\",\n    \"createdById\": \"someUserId\",\n    \"createdByName\": \"Some Name\",\n    \"assignedUserId\": \"someUserId\",\n    \"assignedUserName\": \"someName\",\n    \"teamsIds\": [],\n    \"teamsNames\": {}\n}\n```\n\n## Update\n\n### PUT Account/{id}\n\nUpdates an existing Account. Returns its [attributes](../../administration/terms-and-naming.md#attribute).\n\nRequires *edit* access to Account record.\n\nPayload: Record attributes.\n\nExample:\n\n```\nPUT Account/someId\n```\n\nwith payload:\n\n```json\n{\n    \"assignedUserId\": \"someUserId\"\n}\n```\n\n## Delete\n\n### DELETE Account/{id}\n\nRemoves an existing account.\n\nReturns TRUE if success.\n\nRequires *delete* access to Account record.\n\n\nExample:\n\n```\nDELETE Account/someId\n```\n\n## Stream\n\n### GET Account/{id}/stream\n\nReturns stream records of a specific account.\n\nGET parameters: *maxSize*, *limit*.\n\nRequires *stream* access to Account record.\n\n## Relationships\n\nNote: [link](../../administration/terms-and-naming.md#link) names can be obtained at Administration > Entity Manager > click *relationships* on *Account* row > 4th column. Actual types: parent-to-children, one-to-many, many-to-many.\n\nThe list of links available out-of-the-box:\n\n* calls\n* cases\n* contacts\n* documents\n* emails\n* emailsPrimary\n* meetings\n* meetingsPrimary\n* opportunities\n* targetLists\n* tasks\n* tasksPrimary\n\n\n### GET Account/{id}/{link}\n\nReturns a list of related records linked through *link* relation and their total number of records. It's possible to specify filters.\n\nGET parameters are available [here](relationships.md#list-related-records).\n\nRequires *read* access to Account record and *read* access to the scope of the related entity type.\n\n\n### POST Account/{id}/{link}\n\nRelate an existing account with a specific record (or multiple records) through a specific *link*.\n\nRequires *edit* access to Account record and *edit* access to the scope of the related entity type.\n\nPayload parameters are available [here](relationships.md#link).\n\n\n### DELETE Account/{id}/{link}\n\nUnlinks a specific record, linked through a specific link, from an account.\n\nRequires *edit* access to Account record and *edit* access to the scope of the related entity type.\n\nPayload:\n\n1. JSON with `id` string attribute\n2. JSON with `ids` array attribute\n\n"
  },
  {
    "path": "docs/development/api/attachment.md",
    "content": "# API · Attachment\n\n* [Uploading](#uploading)\n* [Downloading](#downloading)\n\n### Uploading\n\n!!! note\n\n    There's also the ability to upload files in chunks. This method is not covered in this article.\n\n`POST Attachment`\n\n* Method: *POST*\n* Endpoint: `Attachment`\n* Headers: `Content-Type: application/json`\n\nPayload attributes:\n\n* name – file name;\n* type – mime type;\n* role – specify value `Attachment`;\n* relatedType – entity type attachment is related to (only for fields of *File* type);\n* relatedId – record ID attachment is related to (only for fields of *File* type);\n* parentType – entity type attachment is related to (only for fields of *Attachment Multiple* type);\n* field – field name of related record attachment is related through;\n* file – file contents.\n\n#### Example (File field)\n\nThe attachment to be stored in the field of *File* type. \n\n##### Step 1. Upload attachment\n\n`POST Attachment`\n\n```json\n{\n    \"name\": \"test.txt\",\n    \"type\": \"text/plain\",\n    \"role\": \"Attachment\",\n    \"relatedType\": \"Document\",\n    \"field\": \"file\",\n    \"file\": \"data:text/plain;base64,FILE_CONTENTS_ENCODED_WITH_BASE64\"\n}\n```\n\nReturns attachment record attributes:\n\n```json\n{\n    \"id\": \"{some-id}\",\n    \"name\": \"test.txt\"\n}\n```\n\n##### Step 2. Set attachment ID in related record\n\nThen you need to send the 2nd request that creates (or updates) the Document record. You will need to fill *fileId* attribute with ID returned after *POST Attachment* request.\n\nCreate:\n\n`POST Document`\n\n```json\n{\n    \"name\": \"document-name\",\n    \"fileId\": \"{id-of-attachment}\"\n}\n```\nUpdate:\n\n`PUT Document/{document-id}`\n\n```json\n{\n    \"fileId\": \"{id-of-attachment}\"\n}\n```\n\n\n#### Example (Attachment-Multiple field)\n\n##### Step 1. Upload attachment\n\nThe attachment to be stored in the field of *Attachment-Multiple* type. \n\n`POST Attachment`\n\n```json\n{\n    \"name\": \"test.txt\",\n    \"type\": \"text/plain\",\n    \"role\": \"Attachment\",\n    \"parentType\": \"Note\",\n    \"field\": \"attachments\",\n    \"file\": \"data:text/plain;base64,FILE_CONTENTS_ENCODED_WITH_BASE64\"\n}\n```\n\n##### Step 2. Set attachment ID in parent record\n\nThen you need to send the 2nd request that creates (or updates) the parent Note record. You need to specify *attachmentsIds* attribute with an array that contains ID returned after *POST Attachment* request.\n\nCreate:\n\n\n`POST Note`\n\n```json\n{\n    \"post\": \"Some text\",\n    \"type\": \"Post\",\n    \"attachmentsIds\": [\"{id-of-attachment}\"]\n}\n```\n\nUpdate:\n\n`PUT Note/{id-of-note-record}`\n\n```json\n{\n    \"attachmentsIds\": [\"{id-of-attachment}\"]\n}\n```\n\nNote: If you are attaching to an existing record, you need also to add current attachments, otherwise they will be unlinked from the record.\n\n\n### Downloading\n\n`GET Attachment/file/{id}`\n\nWhere `{id}` is an ID of the attachment record.\n\nReturns attachment contents.\n"
  },
  {
    "path": "docs/development/api/crud.md",
    "content": "# API · CRUD Operations\n\nCRUD stands for create, read, update, delete.\n\n!!! note\n\n    You can obtain the list of [entity types](../../administration/terms-and-naming.md#entity-type) under: Administration > Entity Manager > the left column.\n\n    Available entity attributes and their details can be obtained under: Administration > Entity Manager > {Entity Type} > Fields. You can *View Details* of a particular field to explore its attributes.\n\n* [List](#list)\n* [Read](#read)\n* [Create](#create)\n* [Update](#update)\n* [Delete](#delete)\n\n\n### List\n\n`GET {entityType}`\n\nReturns a list of records of a specific entity type.\n\nGET parameters:\n\n* `maxSize` – *int* – max size.\n* `offset` – *int* – offset.\n* `where` – *array* – filters. An alias `whereGroup` can be used instead to prevent false positive firewall blocking. \n* `orderBy` – *string* – attribute to sort by.\n* `order` – *\"asc\"|\"desc\"* – sort direction.\n* `select` – *string* – list of [attributes](../../administration/terms-and-naming.md#attribute) to be returned, separated by comma; if not specified, then all attributes will be returned; whitespaces are not allowed. An alias `attributeSelect` can be used instead to prevent false positive firewall blocking.\n\nExample:\n\n`GET Account?offset=0&maxSize=20`\n\nReturns:\n```\n{\n  \"list\": [... array of records...],\n  \"total\": {totalCountOfRecords}\n}\n```\n\nNote that if the record count is disabled for the entity type, -1 or -2 will be returned instead of the actual total number of records. -1 means that there are more records – pagination can be used to retrieve the next portion.\n\nSee [more info](../api-search-params.md) about search parameters.\n\nAdditional headers:\n\n* `X-No-Total: true` – won't return a total number of records (can be reasonable for big tables, the request will be processed faster).\n\n### Read\n\n`GET {entityType}/{id}`\n\nReturns [attributes](../../administration/terms-and-naming.md#attribute) of a specific record.\n\nExample:\n\n`GET Account/5564764442a6d024c`\n\n### Create\n\n`POST {entityType}`\n\nCreates a new record of a specific entity type.\n\nPayload: Object of entity [attributes](../../administration/terms-and-naming.md#attribute).\n\nReturns attributes of the created record.\n\nHeaders:\n\n*  `Content-Type: application/json`\n\nExample:\n\n`POST Account`\n\nPayload:\n```\n{\n  \"name\": \"Test\",\n  \"assignedUserId\": \"1\"\n}\n```\n\nAdditional headers:\n\n* `X-Skip-Duplicate-Check: true` – skips checking for duplicates (won't return 409 Error if a duplicate record is found).\n\n### Update\n\n`PUT {entityType}/{id}`\n\nUpdates an existing record.\n\nPayload: Object of entity [attributes](../../administration/terms-and-naming.md#attribute) needed to be changed.\n\nReturns attributes of the updated record.\n\nHeaders:\n\n*  `Content-Type: application/json`\n\nExample:\n\n`PUT Account/5564764442a6d024c`\n\nPayload:\n\n```\n{\n  \"assignedUserId\": \"1\"\n}\n```\n\n### Delete\n\n`DELETE {entityType}/{id}`\n\nDeletes an existing record.\n\nReturns `true`.\n\nExample:\n\n`DELETE Account/5564764442a6d024c`\n"
  },
  {
    "path": "docs/development/api/currency-rate.md",
    "content": "# API · CurrencyRate\n\n### Getting rates\n\n`GET CurrencyRate`\n\nReturns currency rates.\n\nRequires *read* access to *Currency* scope.\n\n### Updating rates\n\n`PUT CurrencyRate`\n\nUpdates currency rates. One or multiple currency rates should be specified in a payload.\n\nRequires *edit* access to *Currency* scope.\n\nPayload example:\n\n```json\n{\n    \"EUR\": 1.11,\n    \"UAH\": 0.037\n}\n```\n"
  },
  {
    "path": "docs/development/api/i18n.md",
    "content": "# API · I18n (Internalization)\n\n## Getting all labels\n\n`GET I18n`\n\nReturns all application labels. If authorized as an API User, labels will be translated to the default language (set in Administration > System). If authorized as a regular user (via Basic Authentication), then labels will be translated to the language set in preferences of that user. By passing GET parameter `default=true` it will force to return in the default language.\n\nResponse data:\n\n* entity types and scopes: \"Global\" > \"scopeNames\" & \"Global\" > \"scopeNamesPlural\"\n* field labels: EntityType > \"fields\"\n* link labels: EntityType > \"links\"\n"
  },
  {
    "path": "docs/development/api/metadata.md",
    "content": "# API · Metadata\n\n## Getting metadata\n\n`GET Metadata`\n\nReturns application metadata. Note that not all metadata is available for reading from the outside – some data is stripped from the result.\n\nQuery params:\n\n* key – a specific path to return; e.g. `entityDefs.Lead.fields.status.options`; as of v8.2.\n"
  },
  {
    "path": "docs/development/api/relationships.md",
    "content": "# API · Related records\n\n!!! note\n    You can obtain the list of [link](../../administration/terms-and-naming.md#link) names at Administration > Entity Manager > click relationships on a specific entity type > 4th column. Actual types: parent-to-children, one-to-many, many-to-many.\n\n* [List related records](#list-related-records)\n* [Link](#link)\n* [Unlink](#unlink)\n\n### List related records\n\n`GET {entityType}/{id}/{link}`\n\nGET parameters:\n\n* `maxSize` - (int) max size\n* `offset` - (int) offset\n* `where` - (array) filters\n* `orderBy` - (string) attribute to sort by\n* `order` - (string: 'asc' | 'desc') sort direction\n* `select` - (string) list of attributes to be returned, separated by comma; if not specified, then all fields will be returned\n\nYou can find more info about search params [here](../api-search-params.md).\n\nExample:\n\n`GET Account/5564764442a6d024c/opportunities`\n\nReturns:\n\n```\n{\n  \"list\": [... array of records...],\n  \"total\": {totalCountOfRecords}\n}\n```\n\nSee [more info](../api-search-params.md) about search parameters.\n\n### Link\n\n`POST {entityType}/{id}/{link}`\n\nRelates two records.\n\nPayload:\n\n* `id` - ID of the record to relate with\n* `ids` - array of IDs of the records to relate with\n* `massRelate` - optional, false or true, whether to use search criteria that will be used instead of specific ids\n* `where` - optional [search criteria](../api-search-params.md#where)\n\nHeaders:\n\n*  `Content-Type: application/json`\n\nExample:\n\n`POST Account/5564764442a6d024c/opportunities`\n\nPayload:\n```\n{\n  \"id\": \"55646fd85955c28c5\"\n}\n```\n\n### Unlink\n\n`DELETE {entityType}/{id}/{link}`\n\nUnrelates two records.\n\nPayload fields:\n\n* `id` - ID of related record to remove\n* `ids` - array of IDs of related records to remove\n\nHeaders:\n\n*  `Content-Type: application/json`\n\nExample:\n\n`DELETE Account/5564764442a6d024c/opportunities`\n\nPayload:\n```\n{\n  \"id\": \"55646fd85955c28c5\"\n}\n```\n"
  },
  {
    "path": "docs/development/api/stream.md",
    "content": "# API · Stream\n\n### List stream records for the current user\n\n`GET Stream`\n\nGet parameters:\n\n* `offset` – (int) offset\n* `maxSize` – (int) max size\n\n### List stream notes of a specific record\n\n`GET {entityType}/{id}/stream`\n\nGet parameters:\n\n* `offset` – (int) offset\n* `maxSize` – (int) max size\n\n### Follow record\n\n`PUT {entityType}/{id}/subscription`\n\n### Unfollow record\n\n`DELETE {entityType}/{id}/subscription`\n\n### Post to stream\n\n`POST Note`\n\nPayload attributes:\n\n* `type` – should be the string value `Post`\n* `parentId` – ID of the record to post to\n* `parentType` – entity type of the record to post to\n* `post` – text to post\n* `attachmentsIds` – optional, array of IDs of attachments (should be uploaded in separate request beforehand)\n\nPayload example:\n\n```json\n{\n  \"type\": \"Post\",\n  \"parentId\": \"someId\",\n  \"parentType\": \"Case\",\n  \"post\": \"This is a test\\n\\nHello\"\n}\n```\n"
  },
  {
    "path": "docs/development/api-action.md",
    "content": "# API actions\n\nThis article would be useful for those who needs to create a custom [API](api.md) action.\n\n## Routing\n\nYou can define a specific route to access your API action (endpoint).\n\nDefault routes are defined here: `application/Espo/Resources/routes.json`.\n\nCustom routes can be defined in the following places:\n\n* `custom/Espo/Modules/{ModuleName}/Resources/routes.json`\n* `custom/Espo/Custom/Resources/routes.json`\n\n### Example\n\n`routes.json`:\n\n```json\n[\n    {\n        \"route\": \"/MyAction\",\n        \"method\": \"get\",\n        \"actionClassName\": \"Espo\\\\Modules\\\\MyModule\\\\Api\\\\GetMyAction\"\n    },\n    {\n        \"route\": \"/MyScope/:id/something\",\n        \"method\": \"post\",\n        \"actionClassName\": \"Espo\\\\Modules\\\\MyModule\\\\Api\\\\PostMyScopeSomething\"\n    },\n    {\n        \"route\": \"/TestNoAuth\",\n        \"method\": \"get\",\n        \"params\": {\n            \"myParam1\": \"MyValue1\",\n            \"myParam2\": \"MyValue2\"\n        },\n        \"noAuth\": true\n    }\n]\n```\n\nRoute parameters:\n\n* *noAuth* makes the endpoint accessible without authentication.\n* *method* specifies an HTTP method. The most used methods are: *get*, *post*, *put*, *delete*.\n* *actionClassName* defines an action class name – the entry point of the route.\n* *params* – parameters passed to the action implementation, rarely used.\n\nA route can contain placeholders (for example, `:id`). The value will be passed to the Action in the Request object.\n\nA route can be processed either by an Action class or by a Controller.\n\nThe API endpoint for a particular route: `https://your-site/api/v1/{route}`.\n\nClearing cache is required after changes in routing files.\n\n## Action\n\n*As of v7.4.*\n\n!!! note\n\n    This is the preferable method.\n\nThe *actionClassName* parameter in a route definition defines the action class. The action class is an entry point. Action classes should implement the `Espo\\Core\\Api\\Action` interface.\n\nExample:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule\\Api;\n\nuse Espo\\Core\\Api\\Action;\nuse Espo\\Core\\Api\\Request;\nuse Espo\\Core\\Api\\Response;\nuse Espo\\Core\\Api\\ResponseComposer;\nuse Espo\\Core\\Exceptions\\BadRequest;\nuse RuntimeException;\n\n// Your service class.\nuse Espo\\Modules\\MyModule\\Service;\n\nclass GetMyAction implements Action\n{\n    public function __construct(\n        // Some class we delegate the logic to.\n        private Service $service,\n    ) {}\n\n    public function process(Request $request): Response\n    {\n        // A route parameter value is passed in an URI, if defined in the route.\n        // E.g. `/Hello/:id`.\n        $id = $request->getRouteParam('id') ?? throw new RuntimeException();\n\n        // Read payload.\n        $someInputValue = $request->getParsedBody()->someKey ??\n            throw new BadRequest(\"Key is not passed in payload.\");\n\n        // Delegate the logic to some class.\n        $data = $this->service->get($id, $someInputValue);\n\n        // Output the result as JSON.\n        return ResponseComposer::json([\n            'someKey' => $data->someKey,\n        ]);\n    }\n}\n```\n\n## Route parameters\n\nYou can define arbitrary route parameters in route definitions. The defined parameters will be available in the action class. It may be useful if you want to use the same action class for different routes but don't want to use a placeholder parameter.\n\n `route.json`:\n\n```json\n[\n    {\n        \"route\": \"Account/:id/myItems\",\n        \"method\": \"get\",\n        \"actionClassName\": \"Espo\\\\Modules\\\\MyModules\\\\Api\\\\GetItems\",\n        \"params\": {\n            \"entityType\": \"Account\"\n        }\n    },\n    {\n        \"route\": \"Contact/:id/myItems\",\n        \"method\": \"get\",\n        \"actionClassName\": \"Espo\\\\Modules\\\\MyModules\\\\Api\\\\GetItems\",\n        \"params\": {\n            \"entityType\": \"Contact\"\n        }\n    }\n]\n```\n\nIn the action method:\n\n```php\n<?php\n$entityType = $request->getRouteParam('entityType') ?? throw new RuntimeException();\n```\n\nInstead of defining a generic route `:entityType/:id/myItems`, we defined two separate routes for specific record types.\n\n---\n\nFor most cases, the sections below won't be relevant and can be skipped.\n\n## Controller\n\n!!! note\n\n    Using controllers is not advisable. Prefer actions instead.\n\nA Controller is an alternative to an Action class. A Controller can contain multiple methods for different actions.\n\nExample of `route.json` with routes mapped to controller actions:\n\n```json\n[\n    {\n        \"route\": \"/Hello/test/:id\",\n        \"method\": \"get\",\n        \"params\": {\n            \"controller\": \"MyController\",\n            \"action\": \"doSomething\",\n            \"id\": \":id\"\n        }\n    },\n    {\n        \"route\": \"/HelloWorld/:name\",\n        \"method\": \"post\",\n        \"params\": {\n            \"controller\": \"MyController\",\n            \"action\": \"helloWorld\",\n            \"name\": \":name\"\n        }\n    }\n]\n```\n\n### Custom controller\n\n\n#### In Custom folder\n\nCreate a file  `custom/Espo/Custom/Controllers/MyController.php`.\n\n```php\n<?php\nnamespace Espo\\Custom\\Controllers;\n\nclass MyController\n{}\n```\n\nClear cache (Administration > Clear Cache).\n\n#### In Module folder\n\nCreate a file `custom/Espo/Modules/MyModule/Resources/metadata/scopes/MyController.json`.\n\n```json\n{\n    \"module\": \"MyModule\"\n}\n```\n\nCreate a file `custom/Espo/Modules/MyModule/Controllers/MyController.php`.\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule\\Controllers;\n\nclass MyController\n{\n    // Dependencies are passed to the constructor.\n}\n```\n\nClear cache after creating a new controller (Administration > Clear Cache).\n\nExample:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule\\Controllers;\n\nuse Espo\\Core\\Api\\Request;\nuse Espo\\Core\\Api\\Response;\nuse SomeDependency;\nuse stdClass;\n\nclass MyController\n{\n    public function __construct(private SomeDependency $someDependency)\n    {}\n\n    // Naming convention: `{method}Action{Action}`.\n    public function putActionUpdate(Request $request, Response $response): stdClass\n    {\n        $id = $request->getRouteParam('id');\n        $data = $request->getParsedBody();\n\n        $result = $this->someDependency->doSomething($id, $data);\n        \n        // Response can be returned or written with `Response::writeBody`.\n        return $result->toStdClass();\n    }\n}\n```\n\n### Extending existing controller\n\n!!! note\n\n    Not recommended.\n\nExample for the *Account* scope.\n\nCreate a file (or modify if it already exists) `custom/Espo/Custom/Controllers/Account.php`.\n\n```php\n<?php\nnamespace Espo\\Custom\\Controllers;\n\nuse Espo\\Core\\Api\\Request;\nuse Espo\\Core\\Api\\Response;\n\nclass Account extends \\Espo\\Modules\\Crm\\Controllers\\Account\n{\n    /**\n     * POST api/v1/Account/action/test\n     */\n    public function postActionTest(Request $request, Response $response): bool\n    {\n        $someParam = $request->getQueryParam('someParam'); // GET parameter        \n        $data = $request->getParsedBody(); // payload\n        \n        $someValue = $data->someKey ?? null;\n\n        $response->setStatus(201); // example how to set custom response status code\n\n        // call some service class here\n\n        return $someData; // can be true, false, array or object.\n    }\n\n    /**\n     * GET api/v1/Account/action/test\n     */\n    public function getActionTest(Request $request, Response $response): void\n    {\n        $someParam = $request->getQueryParam('someParam'); // GET parameter\n        \n        // call some service class here\n\n        $response->writeBody('true');\n    }\n}\n```\n\n!!! note\n    \n    For the *Account* entity type, we extend `Espo\\Modules\\Crm\\Controllers\\Account`. \n    Some entity types might not have controllers in `Espo\\Modules\\Crm\\Controllers` namespace. They are defined in `Espo\\Controllers` namespace.\n\n## CRUD actions\n\nIf a controller is used, the CRUD operations for a record are implemented using the methods shown below.\n\n```php\n<?php\nnamespace Espo\\Custom\\Controllers;\n\nuse Espo\\Core\\Api\\Request;\nuse Espo\\Core\\Api\\Response;\n\nclass MyController\n{   \n    // Creates a record.\n    public function postActionCreate(Request $request, Response $response): void\n    {}\n\n    // Reads a record.\n    public function getActionRead(Request $request, Response $response): void\n    {}\n    \n    // Updates a record.\n    public function putActionUpdate(Request $request, Response $response): void\n    {}\n    \n    // Deletes a record.\n    public function deleteActionDelete(Request $request, Response $response): void\n    {}\n}\n```\n"
  },
  {
    "path": "docs/development/api-client-go.md",
    "content": "# API Client implementation in Go\r\n\r\n- [API Key authentication](#using-api-key-authentication)\r\n- [Basic authentication](#using-basic-authentication)\r\n- [Making a list GET request](#making-a-list-get-request)\r\n- [Making a read GET request](#making-a-read-get-request)\r\n- [Making a create POST request](#making-a-create-post-request)\r\n- [Making an update PUT request](#making-an-update-put-request)\r\n- [Making a delete DELETE request](#making-a-delete-delete-request)\r\n\r\n!!! note\r\n\r\n    This is an unofficial (3rd party) client.\r\n\r\nFor the source code, refer to [GitHub](https://github.com/definitepotato/espocrm).\r\n\r\n## Using API Key Authentication\r\n\r\n```go\r\nimport \"github.com/definitepotato/espocrm\"\r\n\r\nclient := espocrm.NewApiClient(\r\n    \"https://espocrm.example.com\",\r\n    espocrm.WithApiKeyAuth(\"Your API Key here\"),\r\n)\r\n```\r\n\r\n## Using Basic Authentication\r\n\r\n(**this is highly discouraged**)\r\n\r\n```go\r\nimport \"github.com/definitepotato/espocrm\"\r\n\r\nclient := espocrm.NewApiClient(\r\n    \"https://espocrm.example.com\",\r\n    espocrm.WithBasicAuth(\"username\", \"password\"),\r\n)\r\n```\r\n\r\n## Making a list GET request\r\n\r\n```go\r\nimport \"github.com/definitepotato/espocrm\"\r\n\r\nparameters := espocrm.NewParameters(\r\n    espocrm.SetWhere([]espocrm.Where{\r\n        {\r\n            Type: espocrm.Equals,\r\n            Attribute: \"myAttribute\",\r\n            Value: \"myValue\",\r\n        },\r\n    }),\r\n)\r\n\r\nclient := espocrm.NewApiClient(\r\n    \"https://espocrm.example.com\",\r\n    espocrm.WithApiKeyAuth(\"Your API Key here\"),\r\n)\r\n\r\ncontacts, err := client.List(\"Contact\", parameters)\r\n```\r\n\r\n## Making a read GET request\r\n\r\n```go\r\nimport \"github.com/definitepotato/espocrm\"\r\n\r\nclient := espocrm.NewApiClient(\r\n    \"https://espocrm.example.com\",\r\n    espocrm.WithApiKeyAuth(\"Your API Key here\"),\r\n)\r\n\r\ncontact, err := client.Read(\"Contact\", \"78abc123def456\")\r\n```\r\n\r\n## Making a create POST request\r\n\r\n```go\r\nimport \"github.com/definitepotato/espocrm\"\r\n\r\nnewContact := `\"{ \"name\": \"Test\", \"assignedUserId\": \"1\" }\"`\r\n\r\nclient := espocrm.NewApiClient(\r\n    \"https://espocrm.example.com\",\r\n    espocrm.WithApiKeyAuth(\"Your API Key here\"),\r\n)\r\n\r\nattributes, err := client.Create(\"Contact\", newContact)\r\n```\r\n\r\n## Making an update PUT request\r\n\r\n```go\r\nimport \"github.com/definitepotato/espocrm\"\r\n\r\ncontactID := \"993bdd81479dff4\"\r\nupdatePayload := `\"{ assignedUserId\": \"1\" }\"`\r\n\r\nclient := espocrm.NewApiClient(\r\n    \"https://espocrm.example.com\",\r\n    espocrm.WithApiKeyAuth(\"Your API Key here\"),\r\n)\r\n\r\nattributes, err := client.Update(\"Contact\", contactID, updatePayload)\r\n```\r\n\r\n## Making a delete DELETE request\r\n\r\n```go\r\nimport \"github.com/definitepotato/espocrm\"\r\n\r\ncontactID := \"78abc123def456\"\r\nclient := espocrm.NewApiClient(\r\n    \"https://espocrm.example.com\",\r\n    espocrm.WithApiKeyAuth(\"Your API Key here\"),\r\n)\r\n\r\nstatus, err := client.Delete(\"Contact\", contactID)\r\n```\r\n"
  },
  {
    "path": "docs/development/api-client-java.md",
    "content": "# API Client implementation in Java\r\n\r\n- [Installing](#installing)\r\n- [Usage](#usage)\r\n\r\n!!! note\r\n\r\n    This is an unofficial (3rd party) client.\r\n\r\nFor the source code, refer to the GitHub repository [here](https://github.com/TobiasDeBruijn/espocrm-java).\r\n\r\n## Installing\r\n\r\n[![Maven Central](https://img.shields.io/maven-central/v/dev.array21/espocrm-api-client.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22dev.array21%22%20AND%20a:%22espocrm-api-client%22)\r\n\r\nThe client is available on the Maven Central repository.  \r\nMinimum supported Java version: 11\r\n\r\n\r\nMaven:\r\n```xml\r\n<dependency>\r\n  <groupId>dev.array21</groupId>\r\n  <artifactId>espocrm-api-client</artifactId>\r\n  <version>VERSION</version>\r\n</dependency>\r\n```\r\n\r\nGradle:\r\n```groovy\r\nrepositories {\r\n    mavenCentral()\r\n}\r\n\r\ndependencies {\r\n    implementation 'dev.array21:espocrm-api-client:VERSION'\r\n}\r\n```\r\n\r\n## Usage\r\n```java\r\nimport java.io.IOException;\r\nimport java.security.InvalidKeyException;\r\n\r\nimport dev.array21.espocrm.client.ClientBuilder;\r\nimport dev.array21.espocrm.client.EspoApiClient;\r\nimport dev.array21.espocrm.client.RequestException;\r\nimport dev.array21.espocrm.types.Where;\r\nimport dev.array21.espocrm.types.FilterType;\r\nimport dev.array21.espocrm.types.Method;\r\nimport dev.array21.espocrm.types.Params;\r\n\r\npublic class ExampleClass {\r\n    public static void main(String[] args) {\r\n        EspoApiClient client = new ClientBuilder()\r\n            .setHost(\"YOUR ESPOCRM HOST\")\r\n            .setApiKey(\"YOUR ESPOCRM API KEY\")\r\n            .setSecretKey(\"YOUR ESPOCRM SECRET KEY\") // for HMAC method\r\n            .build();\r\n\r\n        Where[] whereFilter = new Where[] {\r\n            new Where(FilterType.EQUALS, \"SomeEspoCrmField\").setValue(\"itMustBeEqualToThis\")\r\n        }\r\n\r\n        Params requestParams = new Params()\r\n            .setOffset(0)\r\n            .setMaxSize(50)\r\n            .setSelect(\"id\")\r\n            .setOrderBy(\"id\")\r\n            .setOrder(Order.DESC)\r\n            .setWhere(whereFilter);\r\n\r\n        try {\r\n            String jsonResponse = client.requestGet(\"Account\", requestParams);\r\n        } catch(InvalidKeyException e) {\r\n            e.printStackTrace();\r\n        } catch(IOException e) {\r\n            e.printStackTrace();\r\n        } catch(RequestException e) {\r\n            e.printStackTrace();\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n\r\n"
  },
  {
    "path": "docs/development/api-client-js.md",
    "content": "# API Client Implementation in Javascript (Nodejs)\n\n* [Usage](#usage)\n* [Module](#module)\n\n## Usage\n\n```js\n\nconst Client = require('./espocrm-api-client');\n\nconst client = new Client(\n    'https://your-espocrm-site',\n    'API_KEY',\n    'SECRET_KEY' // optional, if hmac auth is used\n);\n\n// POST example\n\nconst payload = {\n    name: 'Some name',\n};\n\nclient\n    .request('POST', 'Account', payload)\n    .then(response => {\n        // success\n        console.log(response);\n    })\n    .catch(response => {\n        // error\n        console.log(response.statusCode, response.statusMessage);\n    });\n\n// GET example\n\nconst params = {\n    maxSize: 5,\n    where: [\n        {\n            type: 'equals',\n            attribute: 'type',\n            value: 'Customer',\n        },\n    ],\n    select: ['id', name'],\n};\n\nclient\n    .request('GET', 'Account', params)\n    .then(response => {\n        console.log(response);\n    })\n    .catch(response => {\n        // error\n        console.log(response.statusCode, response.statusMessage);\n    });\n```\n\n## Module\n\nFile `espocrm-api-client.js`:\n\n```js\nclass Client {\n\n    /**\n     *\n     * @param {string} url\n     * @param {string} apiKey\n     * @param {string|null} [secretKey]\n     * @param {{\n     *     port?: number,\n     *     timeout?: number,\n     * }} [options]\n     */\n    constructor(url, apiKey, secretKey = null, options = {}) {\n        this.url = url;\n        this.apiKey = apiKey;\n        this.secretKey = secretKey;\n\n        if (this.url.substr(-1) === '/') {\n            this.url = this.url.substr(0, this.url.length -1);\n        }\n\n        this.options = options;\n\n        this.urlPath = '/api/v1/';\n        this.isHttps = url.toLowerCase().indexOf('https') === 0;\n    }\n\n    /**\n     *\n     * @param {'GET'|'POST'|'PUT'|'DELETE'|'PATCH'|'OPTIONS'} method\n     * @param {string} action\n     * @param {Record} [data]\n     * @return {Promise}\n     */\n    request(method, action, data) {\n        method = method || 'GET';\n        method = method.toUpperCase();\n\n        let url = this._buildUrl(action);\n\n        const headers = {};\n\n        if (this.apiKey && this.secretKey) {\n            const crypto = require('crypto');\n\n            const string = method + ' /' + action;\n\n            const authString = this.apiKey + ':' +\n                crypto.createHmac('sha256', this.secretKey).update(string).digest('hex');\n\n            const authPart = Buffer.from(authString).toString('base64');\n\n            headers['X-Hmac-Authorization'] = authPart;\n        } else if (this.apiKey) {\n            headers['X-Api-Key'] = this.apiKey;\n        } else {\n            throw new Error('Api-Key is not set.');\n        }\n\n        let postData;\n\n        if (data) {\n            if (method === 'GET') {\n                const querystring = require('querystring');\n\n                url += '?' + querystring.stringify({searchParams: JSON.stringify(data)});\n            } else {\n                postData = JSON.stringify(data);\n\n                headers['Content-Type'] = 'application/json';\n                headers['Content-Length'] = Buffer.byteLength(postData);\n            }\n        }\n\n        return new Promise((resolve, reject) => {\n            const o = {\n                headers: headers,\n                method: method,\n            };\n\n            if (this.options.port) {\n                o.port = this.options.port;\n            }\n\n            if (this.options.timeout) {\n                o.timeout = this.options.timeout;\n            }\n\n            const h = this.isHttps ? require('https') : require('http');\n\n            const req = h.request(url, o, res => {\n                let data = '';\n\n                res.on('data', chunk => {\n                    data += chunk;\n                });\n\n                res.on('end', () => {\n                    if (res.statusCode < 200 || res.statusCode > 299) {\n                        reject(res);\n\n                        return;\n                    }\n\n                    try {\n                        data = JSON.parse(data);\n                    } catch (e) {\n                        console.error(`Error: Could not parse response`);\n                        reject({});\n\n                        return;\n                    }\n\n                    resolve(data, res);\n                });\n            });\n\n            req.on('error', e => {\n                console.error(`Error: ${e.message}`);\n\n                reject(e);\n            });\n\n            if (data && method !== 'GET') {\n                req.write(postData);\n            }\n\n            req.end();\n        });\n    }\n\n    _buildUrl(action) {\n        return this.url + this.urlPath + action;\n    }\n}\n\nif (module && module.exports) {\n    module.exports = Client;\n}\n```\n"
  },
  {
    "path": "docs/development/api-client-php.md",
    "content": "# API Client Implementation in PHP\n\nRequire [Espo Api Client](https://github.com/espocrm/php-espo-api-client) with Composer:\n\n```\ncomposer require espocrm/php-espo-api-client\n```\nBefore executing this script, create an API user with the needed permissions.\n\n### Usage\n\n```php\nuse Espo\\ApiClient\\Client;\n\n$client = new Client('https://your-espocrm-site');\n$client->setApiKey('API_KEY');\n\n// The second parameter is the path.\n$response = $client->request(Client::METHOD_POST, 'Lead', [\n    'firstName' => 'Test',\n    'lastName' => 'Hello',\n]);\n\n$response = $client->request(Client::METHOD_GET, 'Opportunity', [\n    'maxSize' => 10,\n    'select' => 'id,name,assignedUserId',\n    'orderBy' => 'createdAt',\n    'order' => 'desc',\n    'primaryFilter' => 'open',\n]);\n\n$parsedBody = $response->getParsedBody();\n\n$fileContents = $client->request(Client::METHOD_GET, \"Attachment/file/$attachmentId\")\n    ->getBodyPart();\n```\n\n### Api Key Authentication\n\n```php\n$client = new Client('https://your-espocrm-site');\n$client->setApiKey('API_KEY');\n```\n\n### HMAC Authentication\n\n```php\n$client = new Client('https://your-espocrm-site');\n$client->setApiKey('API_KEY');\n$client->setSecretKey('SECRET_KEY');\n```\n"
  },
  {
    "path": "docs/development/api-client-python.md",
    "content": "# API Client Implementation in Python\n\n!!! note\n\n    You need to have *requests* package installed with: `pip install requests`.\n\n## Class\n\nFile: `espo_api_client.py`:\n\n```python\nimport requests\nimport urllib\n\nclass EspoAPIError(Exception):\n    \"\"\"An exception class for the client\"\"\"\n\ndef http_build_query(data):\n    parents = list()\n    pairs = dict()\n\n    def renderKey(parents):\n        depth, outStr = 0, ''\n        for x in parents:\n            s = \"[%s]\" if depth > 0 or isinstance(x, int) else \"%s\"\n            outStr += s % str(x)\n            depth += 1\n        return outStr\n\n    def r_urlencode(data):\n        if isinstance(data, list) or isinstance(data, tuple):\n            for i in range(len(data)):\n                parents.append(i)\n                r_urlencode(data[i])\n                parents.pop()\n        elif isinstance(data, dict):\n            for key, value in data.items():\n                parents.append(key)\n                r_urlencode(value)\n                parents.pop()\n        else:\n            pairs[renderKey(parents)] = str(data)\n\n        return pairs\n    return urllib.parse.urlencode(r_urlencode(data))\n\nclass EspoAPI:\n\n    url_path = '/api/v1/'\n\n    def __init__(self, url, api_key):\n        self.url = url\n        self.api_key = api_key\n        self.status_code = None\n\n    def request(self, method, action, params=None):\n        if params is None:\n            params = {}\n\n        headers = {\n        }\n\n        headers['X-Api-Key'] = self.api_key\n\n        kwargs = {\n            'url': self.normalize_url(action),\n            'headers': headers,\n        }\n\n        if method in ['POST', 'PATCH', 'PUT']:\n            kwargs['json'] = params\n        else:\n            kwargs['url'] = kwargs['url'] + '?' + http_build_query(params)\n\n        response = requests.request(method, **kwargs)\n\n        self.status_code = response.status_code\n\n        if self.status_code != 200:\n            reason = self.parse_reason(response.headers)\n            raise EspoAPIError(f'Wrong request, status code is {response.status_code}, reason is {reason}')\n\n        data = response.content\n        if not data:\n            raise EspoAPIError('Wrong request, content response is empty')\n\n        return response.json()\n\n    def normalize_url(self, action):\n        return self.url + self.url_path + action\n\n    @staticmethod\n    def parse_reason(headers):\n        if 'X-Status-Reason' not in headers:\n            return 'Unknown Error'\n\n        return headers['X-Status-Reason']\n```\n\n## Usage\n\n```python\nfrom espo_api_client import EspoAPI\n\nclient = EspoAPI('https://address-of-your-espocrm', 'paste_api_key_here')\n\n# Create a lead\ndata = {\n    'firstName': 'John',\n    'lastName': 'Does',\n    'phoneNumber': '+11111-22222-33333',\n    'source': 'Web Site',\n    'assignedUserId': '1',\n    'industry': 'Legal',\n}\nprint(client.request('POST', 'Lead', data))\n\n# Update\nprint(client.request('PUT', 'Lead/5b3c37b74b19680f1', {'lastName': 'Alice'}))\n\n# Get accounts\nprint(client.request('GET', 'Account'))\n\n# Get accounts with search params\nparams = {\n    \"select\": \"id,phoneNumber\",\n    \"where\": [\n        {\n            \"type\": \"equals\",\n            \"attribute\": \"phoneNumber\",\n            \"value\": '+1',\n        },\n    ],\n}\nprint(client.request('GET', 'Account', params))\n\n# Delete an opportunity\nprint(client.request('DELETE', 'Opportunity/5b3b0b8c0b2b8bea5'))\n```\n"
  },
  {
    "path": "docs/development/api-client-rust.md",
    "content": "# API Client implementation in Rust\r\n\r\n* [Installation](#installation)\r\n* [HMAC authorization](#hmac-authorization)\r\n* [API Key authorization](#api-key-authorization)\r\n* [Basic authorization](#basic-authorization)\r\n* [Making a request](#making-a-request)\r\n\r\n!!! note\r\n\r\n    This is an unofficial (3rd party) client.\r\n\r\nFor the full documentation, refer to [docs.rs](https://docs.rs/espocrm-rs/latest/espocrm_rs/).\r\nFor the source code, refer to [GitHub](https://github.com/TobiasDeBruijn/espocrm-rs).\r\n\r\n## Installation\r\n[![Crates.io](https://img.shields.io/crates/v/espocrm-rs)](https://crates.io/crates/espocrm-rs)  \r\nThe crate is on crates.io, so you can add it by adding it to your `[dependencies]` in your Cargo.toml:\r\n```toml\r\n[dependencies]\r\nespocrm-rs = \"0.2.0\"\r\n```\r\n\r\nFor the latest version, refer to [crates.io](https://crates.io/crates/espocrm-rs).\r\n\r\n## HMAC authorization\r\n\r\n```rust\r\nuse espocrm_rs::EspoApiClient;\r\n\r\nlet client = EspoApiClient::new(\"https://espocrm.example.com\")\r\n    .set_api_key(\"Your API Key here\")\r\n    .set_secret_key(\"Your API Secret\")\r\n    .build();\r\n```\r\n## API Key authorization\r\n\r\n```rust\r\nuse espocrm_rs::EspoApiClient;\r\nlet client = EspoApiClient::new(\"https://espocrm.example.com\")\r\n    .set_api_key(\"Your API Key here\")\r\n    .build();\r\n```\r\n\r\n## Basic authorization\r\n\r\n```rust\r\nuse espocrm_rs::EspoApiClient;\r\nlet client = EspoApiClient::new(\"https://espocrm.example.com\")\r\n    .set_username(\"Your Username here\")\r\n    .set_password(\"Your Password here\")\r\n    .build();\r\n```\r\n\r\n## Making a request\r\n\r\nTo make a GET request, you need to know a couple things:\r\n\r\n- the request method to use;\r\n- on what to perform the request;\r\n- optionally, any data needed for the request.\r\n\r\n```rust\r\nuse espocrm_rs::{EspoApiClient, Params, Where, FilterType, Value, NoGeneric};\r\nuse reqwest::Method;\r\n\r\nlet params = Params::default()\r\n    .set_offset(0)\r\n    .set_where(vec![\r\n        Where {\r\n            r#type: FilterType::IsTrue,\r\n            attribute: \"exampleField\".to_string(),\r\n            value: None\r\n        },\r\n        Where {\r\n            r#type: FilterType::ArrayAnyOf,\r\n            attribute: \"exampleField2\".to_string(),\r\n            value: Some(Value::array(vec![\r\n                Value::str(\"a\"),\r\n                Value::str(\"b\"),\r\n                Value::str(\"c\")\r\n            ]))\r\n        }\r\n    ])\r\n    .build();\r\n\r\nlet client = EspoApiClient::new(\"https://espocrm.example.com\")\r\n    .set_secret_key(\"Your Secret Key\")\r\n    .set_api_key(\"Your api key\")\r\n    .build();\r\n\r\nlet result = client.request::<NoGeneric>(Method::GET, \"Contact\".to_string(), Some(params), None);\r\n```\r\n\r\nA POST, PUT, etc request is very similar:\r\n```rust\r\nuse espocrm::EspoApiClient;\r\nuse reqwest::Method;\r\nuse serde::Serialize;\r\n\r\n#[derive(Serialize)]\r\nstruct MyData {\r\n    some_value: String,\r\n    some_other_value: i64\r\n}\r\n\r\nlet client = EspoApiClient::new(\"https://espocrm.example.com\")\r\n    .set_secret_key(\"Your Secret Key\")\r\n    .set_api_key(\"Your api key\")\r\n    .build();\r\n\r\nlet data = MyData {\r\n    some_value: \"value\".to_string(),\r\n    some_other_value: 10\r\n}\r\n\r\nlet result = client.request(Method::POST, \"Contact\".to_string(), None, Some(data));\r\n```\r\n\r\nThe MyData struct here will be serialized into JSON data using Serde's Serialize trait.\r\n"
  },
  {
    "path": "docs/development/api-client-zig.md",
    "content": "# API Client implementation in Zig\r\n\r\n- [Installation](#installation)\r\n- [API Key authentication](#using-api-key-authentication)\r\n- [Making a read GET request](#making-a-read-request)\r\n- [Making a list GET request](#making-a-list-request)\r\n- [Making a create POST request](#making-a-create-request)\r\n- [Making an update PUT request](#making-an-update-request)\r\n- [Making a delete DELETE request](#making-a-delete-request)\r\n\r\n!!! note\r\n\r\n    This is an unofficial (3rd party) client.\r\n\r\nFor the source code, refer to [GitHub](https://github.com/definitepotato/espocrmz).\r\n\r\n# Getting Started\r\n\r\nThis Zig `espocrm` library provides an API client for EspoCRM. To get started you'll have to provide the URL where EspoCRM is located and your method of authentication. Read more from the [official documentation](https://docs.espocrm.com/development/api/#authentication).\r\n\r\n## Installation\r\n\r\nAdd this to your build.zig.zon\r\n\r\n```zig\r\n.dependencies = .{\r\n    .espocrmz = .{\r\n        .url = \"https://github.com/definitepotato/espocrmz/archive/refs/heads/master.tar.gz\",\r\n        .hash = \"the correct hash will be suggested by zig at build time\",\r\n    }\r\n}\r\n```\r\n\r\nAdd this to your build.zig\r\n\r\n```zig\r\nconst espocrmz = b.dependency(\"espocrmz\", .{\r\n    .target = target,\r\n    .optimize = optimize,\r\n});\r\nexe.root_module.addImport(\"espocrmz\", espocrmz.module(\"espocrmz\"));\r\n```\r\n\r\nYou can then import the library into your code like this\r\n\r\n```zig\r\nconst espocrm = @import(\"espocrmz\");\r\n```\r\n\r\n## Basic Usage\r\n\r\n### Using API Key Authentication:\r\n\r\n```zig\r\nconst allocator = std.heap.page_allocator;\r\n\r\nconst client: espocrm.Client = .init(\r\n    \"https://espocrm.example.com\",\r\n    .{ .api_key = \"Your API Key here\" },\r\n);\r\n```\r\n\r\n### Making a Read request:\r\n\r\n```zig\r\nconst allocator = std.heap.page_allocator;\r\n\r\nconst result = try client.readEntity(\r\n    allocator,\r\n    \"Contact\",\r\n    \"78abc123def456\",\r\n);\r\ndefer result.deinit();\r\n```\r\n\r\n### Making a List request:\r\n\r\n```zig\r\nvar params = espocrm.Parameters.init();\r\n_ = params.setMaxSize(10).setOrder(espocrm.Parameters.Order.Asc);\r\nconst params_encoded = try params.encode(allocator);\r\n\r\nconst allocator = std.heap.page_allocator;\r\n\r\nconst result = try client.listEntities(allocator, \"Contact\", params, &[_]espocrm.Where{\r\n  .{ .filter_type = espocrm.FilterOption.Equals, .filter_attribute = \"name\", .filter_value = \"Alice\" },\r\n  .{ .filter_type = espocrm.FilterOption.GreaterThan, .filter_attribute = \"age\", .filter_value = \"42\" },\r\n});\r\ndefer result.deinit();\r\n```\r\n\r\n### Making a Create request:\r\n\r\n```zig\r\nconst allocator = std.heap.page_allocator;\r\n\r\nconst new_contact =\r\n  \\\\{\r\n  \\\\  \"name\": \"Alice\",\r\n  \\\\  \"age\": 69\r\n  \\\\}\r\n;\r\n\r\nconst result = try espocrm.createEntity(\r\n    allocator,\r\n    \"Contact\",\r\n    new_contact,\r\n);\r\ndefer result.deinit();\r\n```\r\n\r\n### Making an Update request:\r\n\r\n```zig\r\nconst allocator = std.heap.page_allocator;\r\n\r\nconst update_info =\r\n  \\\\{\r\n  \\\\  \"name\": \"Bob\"\r\n  \\\\}\r\n;\r\n\r\nconst result = try client.updateEntity(\r\n    allocator,\r\n    \"Contact\",\r\n    \"67abe33f5883bd9e\",\r\n    update_info\r\n);\r\ndefer result.deinit();\r\n```\r\n\r\n### Making a Delete request:\r\n\r\n```zig\r\nconst result = try client.deleteEntity(\r\n    allocator,\r\n    \"Contact\",\r\n    \"67abe33f5883bd9e\"\r\n);\r\ndefer result.deinit();\r\n```\r\n"
  },
  {
    "path": "docs/development/api-search-params.md",
    "content": "# API search parameters\n\nFilters and other search parameters can be used with API functions that returns a list of records.\n\n* [Examples](#examples)\n  * [PHP](#php)\n  * [Javascript](#javascript-nodejs)\n  * [Python](#python)\n* [Params](#params)\n* [Where items](#where-items)\n* [Attribute names](#attribute-names)\n\n## Examples\n\n### PHP\n\n```php\n<?php\n\n$url = 'Lead';\n\n$where = [\n    [\n        'type' => 'isNotNull',\n        'attribute' => 'assignedUserId',\n    ],\n    [\n        'type' => 'or',\n        'value' => [\n            [\n                'type' => 'equals',\n                'attribute' => 'status',\n                'value' => 'New',\n            ],\n            [\n                'type' => 'equals',\n                'attribute' => 'status',\n                'value' => 'Assigned',\n            ],\n        ],\n    ],\n];\n\n$boolFilterList = [\n    // 'onlyMy',\n    // 'followed',\n];\n\n// the list of available primary filters can obtained in a select manager class\n$primaryFilter = 'primaryFilter';\n\n// every param is optional\n$params = [\n    'offset' => 0,\n    'maxSize' => 20,\n    'where' => $where,\n    'primaryFilter' => $primaryFilter,\n    'boolFilterList' => $boolFilterList,\n    'select' => 'id,name,assignedUserId,status', \n    'orderBy' => 'createdAt',\n    'order' => 'desc',\n];\n\n$response = $client->request('GET', $url, $params);\n```\n\n### Javascript (Nodejs)\n\n```js\n// every param is optional\nconst params = {\n    maxSize: 5,\n    primaryFilter: 'open',\n    where: [\n        {\n            type: 'equals',\n            attribute: 'priority',\n            value: 'Urgent',\n        }\n    ],\n    select: 'id,name,assignedUserId,assignedUserName',\n};\n\nclient.request('GET', 'Case', params)\n    .then(response => console.log(response))\n```\n\n### Python\n\n```python\nparams = {\n    \"select\": \"id,phoneNumber\",\n    \"where\": [\n        {\n            \"type\": \"equals\",\n            \"attribute\": \"phoneNumber\",\n            \"value\": '+1',\n        },\n    ],\n}\n\nresult = client.request('GET', 'Account', params)\n```\n\n## Params\n\nParameters are passed as query parameters (in GET request).\n\nIt's also possible to pass all search parameters in JSON format in a single query parameter `searchParams`:\n\n```\n?searchParams={JSON_ENCODED_SEARCH_PARAMETERS}\n```\n\n### offset\n\n*Integer*\n\nAn offset for pagination.\n\n### maxSize\n\n*Integer*\n\nHow many records to return.\n\n### select\n\n*String* (or *Array* of strings if search params passed in JSON)\n\nWhat record [attributes](../administration/terms-and-naming.md#attribute) to return. Separated by comma. Whitespaces are not allowed. Specify only attributes that you need, it can improve performance.\n\nExample: `id,name,status,assignedUserId`.\n\nExample in JSON: `[\"id\", \"name\"]`.\n\n!!! note\n\n    An alias GET parameter `attributeSelect` can be used instead to prevent false positive firewall blocking. As of v9.0.\n\n### where\n\n*Array*\n\nSearch criteria. Can contain nested arrays and objects. See more [below](#where-items) more detail.\n\n!!! note\n\n    An alias GET parameter `whereGroup` can be used instead to prevent false positive firewall blocking. As of v9.0.\n\n### primaryFilter\n\n*String*\n\nA primary filter. Primary filters are usually defined in *Select Manager* class.\n\n### boolFilterList\n\n*Array*\n\nBool filters. E.g. *onlyMy*, *followed*.\n\n### orderBy\n\n*String*\n\nAn attribute to order by.\n\n### order\n\n*String*\n\nA direction of order: 'desc' or 'asc'.\n\n\n## Where items\n\nA *Where* parameter is an array if items. Items can contain nested items.\n\nExamples below are given in JSON format. \n\n### equals, notEquals\n\n```json\n{\n    \"type\": \"equals\",\n    \"attribute\": \"status\",\n    \"value\": \"New\"\n}\n```\n\n### greaterThan, lessThan, greaterThanOrEquals, lessThanOrEquals\n\n```json\n{\n    \"type\": \"greaterThan\",\n    \"attribute\": \"amountConverted\",\n    \"value\": 1000.00\n}\n```\n\n### isNull, isNotNull\n\n```json\n{\n    \"type\": \"isNull\",\n    \"attribute\": \"assignedUserId\"\n}\n```\n\n### isTrue, isFalse\n\n```json\n{\n    \"type\": \"isTrue\",\n    \"attribute\": \"someBoolField\"\n}\n```\n\n### linkedWith, notLinkedWith\n\nFor link-multiple fields.\n\n```json\n{\n    \"type\": \"linkedWith\",\n    \"attribute\": \"teams\",\n    \"value\": [\"someTeamId\"]\n}\n```\n\n### isLinked, isNotLinked\n\nFor link-multiple fields. Whether is linked or not linked with any record.\n\n```json\n\n{\n    \"type\": \"isLinked\",\n    \"attribute\": \"teams\"\n}\n```\n\n### in, notIn\n\n```json\n{\n    \"type\": \"in\",\n    \"attribute\": \"status\",\n    \"value\": [\"New\", \"Assigned\"]\n}\n```\n\n### contains, notContains, startsWith, endsWith, like, notLike\n\n```json\n{\n    \"type\": \"contains\",\n    \"attribute\": \"someTextOrVarcharField\",\n    \"value\": \"text\"\n}\n```\n\n### or, and\n\n```json\n{\n    \"type\": \"or\",\n    \"value\": [\n        {\n            \"type\": \"equals\",\n            \"attribute\": \"status\",\n            \"value\": \"New\"\n        },\n        {\n            \"type\": \"equals\",\n            \"attribute\": \"status\",\n            \"value\": \"Assigned\"\n        }\n    ]\n}\n```\n\n### today, past, future, lastSevenDays, currentMonth, lastMonth, nextMonth, currentQuarter, lastQuarter, currentYear, lastYear, currentFiscalYear, lastFiscalYear, currentFiscalQuarter, lastFiscalQuarter\n\n```json\n{\n    \"type\": \"today\",\n    \"attribute\": \"someDateField\"\n}\n```\n\nFor date-time fields:\n\n```json\n{\n    \"type\": \"today\",\n    \"attribute\": \"someDateTimeField\",\n    \"dateTime\": true,\n    \"timeZone\": \"Europe/Kyiv\"\n}\n```\n\n### lastXDays, nextXDays, olderThanXDays, afterXDays, \n\n```json\n{\n    \"type\": \"lastXDays\",\n    \"attribute\": \"someDateField\",\n    \"value\": 2\n}\n```\n\n### between\n\n```json\n{\n    \"type\": \"between\",\n    \"attribute\": \"someNumberOrDateField\",\n    \"value\": [100, 200]\n}\n```\n\n### arrayAnyOf, arrayNoneOf, arrayAllOf\n\nFor array, multi-enum, checkbox fields.\n\n```json\n{\n    \"type\": \"arrayAnyOf\",\n    \"attribute\": \"fieldName\",\n    \"value\": [\"Value 1\", \"Value 2\"]\n}\n```\n### arrayIsEmpty, arrayIsNotEmpty\n\nFor array, multi-enum, checkbox fields.\n\n```json\n{\n    \"type\": \"arrayIsEmpty\",\n    \"attribute\": \"fieldName\"\n}\n```\n\n## Attribute names\n\nAttribute names usually are same as a system field names. Fields are listed at Administration > Entity Manager > ... > Fields.\n\nAttribute names should be in lowerCamelCase.\n\nMore info about attributes [here](../administration/terms-and-naming.md#attribute).\n"
  },
  {
    "path": "docs/development/api-tutorial.md",
    "content": "# API Usage Tutorial\n\n## In EspoCRM\n\n1. Go to Administration > Roles and create a **new role** with permissions you want to grand for the API user.\n2. Go to Administration > API Users and create a new API User. Select the created role. An **API Key** will be generated, you will need to use it in your API requests further.\n\n## In external application\n\n* [PHP](#php)\n* [Javascript (Nodejs)](#javascript-nodejs)\n* [Python](#python)\n\n### PHP\n\nInstall [PHP API client](api-client-php.md) via composer. See usage examples in the same article.\n\nIf something went wrong, check `data/logs` in your EspoCRM. See [error codes](api.md#error-codes).\n\n### Javascript (Nodejs)\n\n1. Create a new JS file: `espocrm-api-client.js` with the code copied from [here](api-client-js.md#module).\n2. Use `require` function to include the module in the place where you want to call EspoCRM API and use it. See the code below.\n\n```js\nconst Client = require('./espocrm-api-client');\n\nconst client = new Client(\n    'https://address-of-your-espocrm',\n    'copy API key from API user to here'\n);\n\n// POST request example\nconst payload = {\n    name: 'some name',\n    type: 'Customer',\n};\n\nclient\n    .request('POST', 'Account', payload)\n    .then(\n        (response) => {\n            // success\n            console.log(response);\n        }\n    )\n    .catch(\n        (res) => {\n            // error\n            console.log(res.statusCode, res.statusMessage);\n        }\n    );\n```\n\nIf something went wrong, check `data/logs` in your EspoCRM. See [error codes](api.md#error-codes).\n\n### Python\n\n1. Create a new file: `espocrm-api-client.py` with the code copied from [here](api-client-python.md#class).\n2. Install *requests* package with the command: `pip install requests`.\n3. Use the client. See the code:\n\n```python\nfrom espo_api_client import EspoAPI\n\nclient = EspoAPI('https://address-of-your-espocrm', 'paste_api_key_here')\n\nparams = {\n    \"select\": \"id,phoneNumber\",\n    \"where\": [\n        {\n            \"type\": \"equals\",\n            \"attribute\": \"emailAddress\",\n            \"value\": 'some@email.com',\n        },\n    ],\n}\n\nresult = client.request('GET', 'Lead', params)\n```\n"
  },
  {
    "path": "docs/development/api.md",
    "content": "# API Overview\n\nEspoCRM is a single page application so the frontend uses REST API to connect with the backend.\nAll operations you perform using the UI, you can implement via API calls using your programming language.\nYou can learn how the API works if you trace what's going in the network tab in your browser console (press F12 key to open the console).\n\nMost of API functions return JSON. POST and PUT requests usually need some data passed in the payload in JSON format. Whenever you send a JSON payload, add the header: `Content-Type: application/json`.\n\nThe root API path is: `api/v1/`.\n\n!!! example \"Example of GET API request\"\n\n    ```\n    GET https://address_of_your_crm/api/v1/Contact/55643ca033f7ab4c5\n    ```\n\nIn this documentation we omit the site URL and `api/v1/` path when we show examples of API endpoints. If you utilize any of our client implementations, they prepend these URL parts automatically.\n\n!!! note\n\n    The API client implementations (available below) automatically adds needed headers and handles authentication.\n\nIn this article:\n\n* [API reference](#api-reference)\n* [Setting up](#setting-up)\n* [Client implementations](#client-implementations)\n* [Authentication](#authentication)\n* [Error codes](#error-codes)\n* [Date and time values](#date-and-time-values)\n\nSee also:\n\n* [Search parameters](api-search-params.md)\n* [Usage tutorial](api-tutorial.md)\n\n## API reference\n\n* [API docs](../api/index.html) – a separate API reference documentation covering CRUD operations for main entity types;\n* [CRUD operations](api/crud.md) – an article on create, read, update, delete operations;\n* [Related records](api/relationships.md) – working with links;\n* [Stream](api/stream.md) – working with the Stream;\n* [CurrencyRate](api/currency-rate.md) – currency conversion rates;\n* [Attachment](api/attachment.md) – working with file attachments;\n* [I18n](api/i18n.md) – internationalization;\n* [Metadata](api/metadata.md) – working with application metadata;\n* [Account](api/account.md) – (to be removed in favor of the API reference)\n\n### OpenAPI specification\n\n*As of v9.3.*\n\nThe OpenAPI specification for your Espo instance (including custom entity types and fields) covering the main CRUD operations can be obtained from the `/api/v1/OpenApi` endpoint. The endpoint is available for admin users and API users with the *OpenAPI* scope enabled in roles.\n\nYou can also obtain the OpenAPI specification under: Administration > API Users > top-right menu > OpenAPI spec.\n\n## Client implementations\n\n* [PHP](api-client-php.md)\n* [Javascript (Nodejs)](api-client-js.md)\n* [Python](api-client-python.md)\n* [Rust](api-client-rust.md)\n* [Java](api-client-java.md)\n* [Go](api-client-go.md)\n* [Zig](api-client-zig.md)\n\n## Setting up\n\nIt's recommended to create a separate **API User** with specific permissions (defined by Roles) and use this user for API calls. You can have multiple API Users for different purposes, give each user specific permissions.\n\nSee in the [tutorial](api-tutorial.md) **how to get started**.\n\nClient implementations require specifying the Site URL. It's an URL that you open in the browser to use EspoCRM.\n\n## Authentication\n\n### Authentication by API Key\n\nThe simplest method of authentication. You need to create an API User (Administration > API Users) with the *API Key* authentication method. Apply a needed role to the user to grant access to specific scopes.\n\nAuthentication header:\n\n```\nX-Api-Key: API_KEY_COPIED_FROM_THE_USER_DETAIL_VIEW\n```\n\n### HMAC Authentication\n\nThe most secure method. You need to create an API User (Administration > API Users) with the *HMAC authentication* method. Apply a needed role to the user to grant access to specific scopes.\n\nAuthentication header:\n\n```\n\"X-Hmac-Authorization: \" + base64Encode(apiKey  + ':' + hashHmacSha256(method + ' /' + uri , secretKey))\n```\nwhere\n\n* `method` – GET, POST, PUT, DELETE;\n* `uri` – a request path, e.g. `Lead/action/convert`.\n\n### Basic Authentication\n\n!!! warning\n\n    This method is not recommended.\n\nFor regular users, the EspoCRM front-end uses the [Basic Authentication](http://en.wikipedia.org/wiki/Basic_access_authentication). A username and password (or token) are passed through the `Authorization` header encoded with Base64.\n\n```\n\"Authorization: Basic \" + base64Encode(username  + ':' + password)\n```\n\nIt's better to use an auth token instead of a password. In this case, you need to provide the username and the password/token in the `Espo-Authorization` header.\n```\n\"Espo-Authorization: \" + base64Encode(username + ':' + passwordOrToken)\n```\n\n1. Obtain an access token with `GET App/user` request with the username and password passed in `Espo-Authorization` header.\n2. Use this token instead of the password in `Espo-Authorization` header for all further requests.\n3. If the request returns 401 error, that means either the username or password are wrong, or the token is not valid anymore.\n\n#### Authentication Token / User Specific Data\n\n`GET App/user`\n\nMake this request to retrieve an access token.\n\nReturns:\n\n* `token` – access token to use\n* `acl` – information about user access\n* `preferences` – user preferences\n* `user` – user record attributes\n\n## Error codes\n\n### 400 Bad request\n\nWhen you create or update a record, this error can mean that you didn't pass a **required field** or it has an empty value. Check the response message or see `data/log` for more details.\n\n### 403 Forbidden\n\nUsually occurs when you **don't have access** to a specific record or action. See `data/log` for more details.\n\n### 404 Not found\n\nUsually occurs when a requested **record doesn't exist**.\n\n### 409 Conflict\n\nAn operation cannot be performed because of a conflict error. For example, cannot edit a locked record, cannot create a duplicate record.\n\n## Date and time values\n\nDate format: *YYYY-MM-DD*. Datetime format: *YYYY-MM-DD HH:mm:ss*.\n\nAll datetime values are represented in UTC timezone, regardless of the settings.\n"
  },
  {
    "path": "docs/development/app-params.md",
    "content": "# App Params\n\nApp params are returned by the back-end once a user logged in. You can use these params in the front-end. For example, Espo has a build-in app-param containing a list of entity types that can be printed to PDF for a current user.\n\n## Custom app params\n\nYou can make the system to return custom parameters. This params can be unique for a current user (different user have different values in params).\n\nCreate a file: `custom/Espo/Custom/Resources/metadata/app/appParams.json`:\n\n```json\n{\n    \"myParam\": {\n        \"className\": \"Espo\\\\Custom\\\\Core\\\\AppParams\\\\MyParam\"\n    }\n}\n```\n\nCreate a file `custom/Espo/Custom/Core/AppParams/MyParam.php`:\n\n```php\n<?php\nnamespace Espo\\Custom\\Core\\AppParams;\n\nuse Espo\\Tools\\App\\AppParam;\n\nclass MyParam implements AppParam\n{\n    public function __construct(\n        // Pass needed dependencies.\n    ) {}\n    \n    public function get(): mixed\n    {\n        // Value fetching logic.\n        // Your value can be a scalar, array or stdClass.\n\n        return $someValue;\n    }\n```\n\nClear cache.\n\nIn the front-end (in a [View](view.md)) you can access your parameter the following way:\n\n```js\nthis.getHelper().getAppParam('myParam');\n```\n"
  },
  {
    "path": "docs/development/attachments.md",
    "content": "# Attachments\n\n## Attachment entity\n\nAttachments are records that represent stored files. These files can be attachments in a stream notes, email attachments, documents, etc.\n\nExample:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule;\n\nuse Espo\\ORM\\EntityManager;\nuse Espo\\Core\\Exceptions\\NotFound;\nuse Espo\\Entities\\Attachment;\n\nclass MyService\n{\n    public function __construct(\n        private EntityManager $entityManager,\n    ) {}\n\n    public function process(string $id): void\n    {\n        $attachment = $this->entityManager\n            ->getRDBRepositoryByClass(Attachment::class)\n            ->getById($id);\n\n        if (!$attachment) {\n            throw new NotFound();\n        }\n\n        $name = $attachment->getName();\n        $size = $attachment->getSize();\n        $type = $attachment->getType();\n    }\n}\n```\n\n### Fields\n\n* name – a file name;\n* size – a size;\n* type – a mime type;\n* parent – a linked record an attachment is related to; used for Attachment-Multiple fields;\n* related – a linked record an attachment is related to; used for File, Image fields, for inline attachments;\n* field – a field an attachment is related through;\n* role – a role, e.g. Attachment, Inline Attachment, Export File.\n* sourceId – an original attachment reference; multiple attachments can refer to one file.\n\n## File storage manager\n\nThe class: `Espo\\Core\\FileStorage\\Manager`.\n\nAn access point for file storing and fetching. Files are represented as Attachment entities. Note that different attachments can be stored in different storages (for example, in local folder, AWS S3). The Manager abstracts away\nhow the file is stored.\n\nUsage example:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule;\n\nuse Espo\\ORM\\EntityManager;\nuse Espo\\Core\\FileStorage\\Manager;\nuse Espo\\Core\\Exceptions\\NotFound;\nuse Espo\\Entities\\Attachment;\n\nclass MyService\n{\n    public function __construct(\n        private EntityManager $entityManager,\n        private Manager $fileStorageManager,\n    ) {}\n\n    public function read(string $id): string\n    {\n        $attachment = $this->entityManager\n            ->getRDBRepositoryByClass(Attachment::class)\n            ->getById($id);\n\n        if (!$attachment) {\n            throw new NotFound();\n        }\n\n        return $this->fileStorageManager->getContents($attachment);\n    }\n\n    public function store(string $contents): string\n    {\n        $attachment = $this->entityManager\n            ->getRDBRepositoryByClass(Attachment::class)\n            ->getNew();\n\n        $attachment->setName('file.txt');\n        $attachment->setType('text/plain');\n\n        $this->entityManager->saveEntity($attachment);\n        $this->fileStorageManager->putContents($attachment, $contents);\n\n        return $attachment->getId();\n    }\n}\n```\n\nAvailable methods:\n\n* exists – check whether a file exists;\n* getSize – get a file size;\n* getContents – get a string;\n* getStream – get a PSR-7 stream;\n* putContents – put a PSR-7 stream;\n* putStream – put a string;\n* unlink – remove from a storage.\n"
  },
  {
    "path": "docs/development/autoload.md",
    "content": "# Autoload\n\nSometimes when developing a module for Espo, you need to include 3rd party libraries via composer. \nAs Espo extensions are not installed via composer and even don't require CLI access to be installed, we needed a mechanism to let Espo know about additional libraries.\n\nYou need to create an *autoload* configuration file `custom/Espo/Modules/{Module}/Resources/autoload.json`:\n\nExample:\n\n```json\n{\n    \"psr-4\": {\n        \"SomeLib\\\\\": \"custom/Espo/Modules/MyModule/vendor/some-lib/src\"\n    },\n    \"psr-0\": {},\n    \"autoloadFileList\": [\n        \"custom/Espo/Modules/MyModule/vendor/some-lib/src/functions.php\"\n    ],\n    \"classmap\": {\n        \"SomeClass\": \"custom/Espo/Modules/MyModule/vendor/some-lib/src/SomeClass.php\"\n    }\n}\n```\n\n\nThis assumes that you installed composer dependencies in your extension's repository. When using an [ext-template](https://github.com/espocrm/ext-template), it will be the directory `src/files/custom/Espo/Modules/MyModule`.\n"
  },
  {
    "path": "docs/development/calculated-fields.md",
    "content": "# Calculated Fields\n\nIt's possible to create a custom not-storable read-only field a value of which will be calculated dynamically upon fetching from the database.\n\nCreate a file `custom/Espo/Custom/Resources/metadata/entityDefs/YourEntityType.json`:\n\n```json\n{\n    \"fields\": {\n        \"yourCustomField\": {\n            \"type\": \"float\",\n            \"notStorable\": true,\n            \"readOnly\": true,\n            \"select\": {\n                \"select\": \"SUB:(field1, field2)\"\n            }\n        }\n    }\n}\n```\n\n`SUB:(field1, field2)` is a [complex expression](../user-guide/complex-expressions.md). In this example the expression subtracts one field from another.\n\nClear cache.\n\nYou will be able to set a label for your new field at Administration > Label Manager or manually in i18n files.\n"
  },
  {
    "path": "docs/development/campaign-unsubscribe-template.md",
    "content": "# Custom template for mass email unsubscribe page\n\n1. Create a file `custom/Espo/Custom/Resources/metadata/clientDefs/Campaign.json`\n\n```json\n{\n    \"unsubscribeTemplate\": \"custom:campaign/unsubscribe\"\n}\n```\n\n2. Create a file `client/custom/res/templates/campaign/unsubscribe.tpl`\n\n```html\n<div class=\"container content\">\n    <div class=\"col-md-6 col-md-offset-2 col-sm-8 col-sm-offset-2\">\n        <div class=\"panel panel-default\">\n            <div class=\"panel-body\">\n                <p>\n                    Custom text\n                </p>\n                <p>\n                    {{translate 'unsubscribed' category='messages' scope='Campaign'}}\n                </p>\n                <p>\n                    <a\n                       class=\"btn btn-default btn-sm\"\n                       href=\"?entryPoint=subscribeAgain&id={{actionData.queueItemId}}\"\n                   >{{translate 'Subscribe again' scope='Campaign'}}</a>\n                </p>\n            </div>\n        </div>\n    </div>\n</div>\n\n```\n\nOriginal content can be copied from the file `client/modules/crm/res/templates/campaign/unsubscribe.tpl`.\n\nThe same logic is available for Subscribe Again template. Use `subscribeTemplate` parameter to define a custom template.\n"
  },
  {
    "path": "docs/development/coding-practices.md",
    "content": "# Backend Coding Practices\n\n## Namespace structure\n\nWithin a module namespace:\n\n- `Entities\\` – entities;\n- `Controllers\\` – record controllers\n  (should not implement any additional logic, only extend the Record controller);\n- `EntryPoints\\` – entry points (accessible by `?entryPoint={name}`);\n- `Hooks\\{EntityType}\\` – hooks (such as before-save, after-save);\n- `Tools\\` – domain level code, for business logic;\n- `Tools\\{DomainName}\\Api\\` – API actions (entry points for API);\n- `Tools\\{DomainName}\\Jobs\\` – jobs;\n- `Tools\\{DomainName}\\Exceptions\\` – domain-level exceptions;\n- `Classes\\` – framework related implementations;\n\n\nThe *Classes* namespace structure (recommendations, not strict rules):\n\n- `Classes\\Select\\{EntityType}\\` – Select framework related implementations;\n- `Classes\\Record\\{EntityType}\\` – Record framework related implementations;\n- `Classes\\Acl\\{EntityType}\\` – ACL framework related implementations;\n- `Classes\\AclPortal\\{EntityType}\\` – ACL framework related implementations related to portals;\n- `Classes\\Jobs\\` – scheduled jobs;\n- `Classes\\AppParams\\` – AppParams implementations;\n- `Classes\\Cleanup\\` – Cleanup implementations;\n- `Classes\\MassAction\\` – MassAction implementations;\n- `Classes\\Action\\` – Action implementations;\n- `Classes\\ConsoleCommands\\` – Action implementations;\n- `Classes\\FieldValidators\\{EntityType}\\{Field}` – field validators;\n"
  },
  {
    "path": "docs/development/coding-rules.md",
    "content": "# Coding Rules\n\n### 1\\. Never pass Container into class constructors. Pass all dependencies separately.\n\n❗ Bad:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule;\n\nuse Espo\\Core\\Container;\n\nclass MyClass\n{\n    public function __constructor(private Container $container)\n    {}\n}\n\n```\n\n✔️ Good:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule;\n\nuse Espo\\Core\\ORM\\EntityManager;\nuse Espo\\Core\\Utils\\Metadata;\n\nclass MyClass\n{\n    public function __constructor(\n        private EntityManager $entityManager,\n        private Metadata $metadata,\n    ) {}\n}\n```\n\nException: Passing the Container may be acceptable for proxy classes.\n\n### 2\\. Never write RAW SQL. Use ORM and Query Builder instead.\n\n✔️ Good:\n\n```php\n<?php\nuse Espo\\Modules\\Crm\\Entities\\Account;\n\n$account = $this->entityManager\n    ->getRDBRepositoryByClass(Account::class)\n    ->select(['id', 'name'])\n    ->where(['type' => Account::TYPE_CUSTOMER])\n    ->order('createdAt')\n    ->findOne();\n```\n\n✔️ Good:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\SelectBuilder;\nuse Espo\\Modules\\Crm\\Entities\\Account;\n\n$query = SelectBuilder::create()\n    ->select(['id', 'name'])\n    ->from(Account::ENTITY_TYPE)\n    ->order('createdAt')\n    ->limit(0, 10)\n    ->build();\n\n$sth = $this->entityManager->getQueryExecutor()->execute($query);\n$rows = $sth->fetchAll();\n```\n\n### 3\\. Specify types for method parameters. Also specify the method return type.\n\n❗ Bad:\n\n```php\n<?php\n\nclass MyClass\n{\n    public function myMethod($request, $text)\n    {}\n}\n```\n\n✔️ Good:\n\n```php\n<?php\n\nclass MyClass\n{\n    public function myMethod(Request $request, string $text): void\n    {}\n}\n```\n\n✔️ Good:\n\n```php\n<?php\n\nclass MyClass\n{\n    public function getString(): ?string\n    {\n        // ...\n    }\n}\n```\n\nAlso avoid the `mixed` type for parameters.\n\n### 4\\. Never return TRUE or FALSE to indicate success or failure. Throw an exception if failure, return NULL for empty result.\n\n✔️ Good:\n\n```php\n<?php\n\nuse Espo\\Core\\Exceptions\\Error;\n\nclass MyClass\n{\n    public function getAsString(): ?string\n    {\n        if ($this->isSomethingWrong()) {\n            throw new Error(\"Something is wrong.\");\n        }\n\n        if ($this->hasNoData()) {\n            return null;\n        }\n\n        return $this->value;\n    }\n}\n```\n\n### 5\\. Don't write comments, write self explanatory code.\n\nIn addition: Do not write *phpdoc* for non-public methods and properties. It's OK if you don't write *phpdoc* at all (unless needed for static analysis).\n\nException: Adding comments may be reasonable in some rare cases.\n\n❗ Bad (excessive documenting and commenting):\n\n```php\n<?php\n// ...\n\n    /**\n     * Sanitize input.\n     *\n     * @param string $input Input string.\n     * @return string Sanitized string.\n     */\n    private function sanitizeInput(string $input): string\n    {\n        // sanitize\n        return Util::sanitize($input);\n    }\n```\n\n✔️ Good:\n\n```php\n<?php\n// ...\n\n    private function sanitizeInput(string $input): string\n    {\n        return Util::sanitize($input);\n    }\n```\n\n✔️ Good (documenting public methods is OK):\n\n```php\n<?php\n// ...\n\n    /**\n     * Run a command.\n     */\n    public function run(Params $params): void\n    {}\n```\n\n❗ Bad:\n\n```php\n<?php\n// ...\n\n// start sanitizing\n$string = filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);\n// end sanitizing\n```\n\n✔️ Good:\n```php\n<?php\n$string = $this->sanitizeString($string);\n```\n\n✔️ Good (explaining some non-obvious cases):\n\n```php\n<?php\n// On the SOME platform we omit doing this due to the risk of processor explosion.\nif ($this->platform === self::SOME) {\n    return;\n}\n```\n\n### 6\\. Import classes in the beginning of the file.\n\n❗ Bad:\n\n```php\n<?php\nnamespace Espo\\Some;\n\nclass SomeClass\n{\n    public function process(): void\n    {\n        $object1 = new \\Espo\\Modules\\MyModule\\Something();\n        $object2 = new \\Espo\\Modules\\MyModule\\AnotherThing();\n        // ...\n        throw new \\RuntimeException();\n    }\n}\n```\n\n✔️ Good:\n\n```php\n<?php\nnamespace Espo\\Some;\n\nuse Espo\\Modules\\MyModule\\Something;\nuse Espo\\Modules\\MyModule\\AnotherThing;\nuse RuntimeException;\n\nclass SomeClass\n{\n    public function process(): void\n    {\n        $object1 = new Something();\n        $object2 = new AnotherThing();\n        // ...\n        throw new RuntimeException();\n    }\n}\n```\n\n### 7\\. Avoid deep levels of indentation.\n\nMore than 2 per method is too much.\n\n❗ Bad:\n\n```php\n<?php\n// ...\n    public function process(): void\n    {\n        if (!$this->isCached()) {\n            foreach ($this->itemList as $item) {\n                if (!$this->hasItem($item)) {\n                    $this->loadItem($item);\n                }\n            }\n        }\n    }\n```\n\n✔️ Better:\n\n```php\n<?php\n// ...\n    public function process(): void\n    {\n        if (!$this->isCached()) {\n            foreach ($this->itemList as $item) {\n                $this->processLoadItem($item);\n            }\n        }\n    }\n```\n\n✔️ Good:\n\n```php\n<?php\n// ...\n    public function process(): void\n    {\n        if (!$this->isCached()) {\n            $this->processLoadItems();\n        }\n    }\n```\n\n### 8\\. Use early returns.\n\n❗ Not good:\n\n```php\n<?php\n// ...\n    private function sizeExceedsLimit(Storage $storage, string $id): bool\n    {\n        $fetchOnlyHeader = false;\n\n        $maxSize = $this->config->get('emailMessageMaxSize');\n\n        if ($maxSize) {\n            $size = $storage->getSize($id);\n\n            if ($size > $maxSize) {\n                $fetchOnlyHeader = true;\n            }\n        }\n\n        return $fetchOnlyHeader;\n    }\n```\n\n✔️ Good:\n\n```php\n<?php\n// ...\n    private function sizeExceedsLimit(Storage $storage, string $id): bool\n    {\n        $maxSize = $this->config->get('emailMessageMaxSize');\n\n        if (!$maxSize) {\n            return false;\n        }\n            \n        $size = $storage->getSize($id);\n        \n        return $size > $maxSize;\n    }\n```\n\n### 8\\. Avoid too many parameters in methods.\n\nLess is better. Four is too much.\n\n❗ Bad:\n\n```php\n<?php\n// ...\n    public function process(string $city, string $country, string $postalCode, string $state): void\n    {}\n```\n\n✔️ Good:\n\n```php\n<?php\n// ...\n    public function process(Address $address): void\n    {}\n```\n\n❗ Bad:\n\n```php\n<?php\n// ...\n    public function find(array $where, int $offset = 0, ?int $limit = null, bool $applyAcl = false): Collection\n    {}\n```\n\n✔️ Good:\n\n```php\n<?php\n\n// Using a builder.\n$collection = $finder\n    ->createBuilder()\n    ->where($where)\n    ->offset($offset)\n    ->limit($limit)\n    ->withAclApplied()\n    ->find();\n```\n\n### 9\\. Methods that return values should not change state. Methods that change state should not return values.\n\nNot a strict rule but in most cases should be followed.\n\n❗ Bad:\n\n```php\n<?php\n\nclass SomeProcessor\n{\n    private bool $isProcessed = false;\n    \n    public function process(): bool\n    {\n        $this->isProcessed = true;\n        \n        // do something\n        \n        return true;\n    }\n}\n```\n\n✔️ Good:\n\n```php\n<?php\n\nclass SomeProcessor\n{\n    public function process(): Result\n    {\n        // do something\n        \n        return Result::createSuccess();\n    }\n}\n```\n\n### 10\\. Prefer composition over inheritance.\n\nAvoid using inheritance.\n\n❗ Bad:\n\n```php\n<?php\n\nclass AccountChecker extends BaseChecker\n{\n    public function check(Entity $entity): bool\n    {\n        $result = parent::check($entity);\n\n        // some additional logic\n\n        return $result;\n    }\n}\n```\n\n✔️ Good:\n\n```php\n<?php\n\nclass AccountChecker implements Checker\n{     \n    // Here we can inject additional dependencies that would be problematic\n    // if we extended the base class.\n    public function __construct(\n        private BaseChecker $baseChecker,\n        private SomeDependency $someDependency,\n    ) {}\n\n    public function check(Entity $entity): bool\n    {\n        $result = $this->baseChecker->check($entity);\n\n        // some additional logic\n\n        return $result;\n     }\n}\n```\n\nThe *protected* visibility should be used very sparsely.\n\n### 11\\. Use DTOs rather than associative arrays or stdClass objects.\n\nUse immutable data transfer objects.\n\n❗ Bad:\n\n```php\n<?php\n\n$data = [\n    'attribute' => $attribute,\n    'value' => $value,\n    'entityType' => $entityType,\n];\n\n$someObject->process($data);\n```\n\n✔️ Good (cloning):\n\n```php\n<?php\n\n$data = Data::create()\n    ->withAttribute($attribute)\n    ->withValue($value)\n    ->withEntityType($entityType);\n    \n$someObject->process($data);    \n```\n\n✔️ Good (building):\n\n```php\n<?php\n\n$data = Data::createBuilder()\n    ->setAttribute($attribute)\n    ->setValue($value)\n    ->setEntityType($entityType)\n    ->build();\n    \n$someObject->process($data);    \n```\n\n✔️ Good (constructor named parameters):\n\n```php\n<?php\n\n$data = new Data(\n    attribute: $attribute,\n    value: $value,\n    entityType: $entityType,\n);\n   \n$someObject->process($data);    \n```\n\n### 12\\. Create domain-level repository classes instead of directly accessing the Entity Manager in business logic.\n\nIt keep business logic independent from persistence details and facilitates testability.\n\n✔️ Good\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule\\Tools\\MyDomain;\n\nclass MyService\n{\n    public function __construct(\n        private MyRepository $repository,\n    ) {}\n\n    public function process(Params $params): void\n    {\n        // It's preferable that the Order is an interface.\n        $orders = $this->repository->getOrders($params);\n\n        // ...\n    }\n}\n```\n\n✔️ Good\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule\\Tools\\MyDomain;\n\nclass MyService\n{\n    public function __construct(\n        private MyRepository $repository,\n    ) {}\n\n    public function process(Order $order): void\n    {\n        // ...\n\n        // It's preferable that the Order is an interface.\n        $this->repository->save($order);\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/collection.md",
    "content": "# Collection\n\nA collection is a list of models. See the [class](https://github.com/espocrm/espocrm/blob/stable/client/src/collection.js).\n\n## Methods\n\n### fetch\n\nFetches a collection (from the back-end). Returns a promise.\n\n```js\ncollection.fetch();\n\ncollection.fetch({\n    remove: false,\n    more: true,\n});\n```\n\nOptions:\n\n* remove – false will prevent removing current models;\n* more – load next portion of records (show-more).\n\nYou can pass custom options and check them in 'change' event listeners.\n\n### clone\n\nClone a collection. Models are kept identical. Returns a collection instance.\n\n### get\n\nGet a model from a collection by an id.\n\n```js\nconst model = collection.get(id);\n```\n\n### at\n\nGet a model by its position in a collection.\n\n```js\nconst model = collection.at(index);\n```\n\n### forEach\n\nIterates through a collection.\n\n```js\ncollection.forEach(model => {});\n```\n\n### add\n\nAdd a model or multiple models to a collection. Firing an 'add' event for each model, and an 'update' event afterwards.\n\n```js\ncollection.add(model);\ncollection.add([model]);\n```\n\n### remove\n\nRemove a model from a collection. Fires a 'remove' event for a model, and an 'update' event afterwards.\n\n```js\ncollection.remove(id);\ncollection.remove(model, {\n    // Suppresses events.\n    silent: true, \n});\n```\n\n### reset\n\nEmpties a collection.\n\n### push\n\nAdd a model to the end.\n\n### pop\n\nRemove and return the last model.\n\n### unshift\n\nAdd a model at the beginning.\n\n### shift\n\nRemove and return the first model.\n\n### resetOrderToDefault\n\nResets order parameters to default.\n\n### setOrder\n\nSets order parameters.\n\n```\n@param {string|null} orderBy\n@param {boolean|'asc'|'desc'|null} [order]\n@param {boolean} [setDefault]\n```\n\n### abortLastFetch\n\nAbort the last fetch.\n\n### hasMore\n\nWhether more records can be fetched.\n\n### setOffset\n\nSet an offset.\n\n```js\ncollection.setOffset(offset);\n```\n\n### getWhere\n\nGet a where-clause.\n\n## Properties\n\n### entityType\n\n*string*\n\nAn entity type.\n\n### length\n\n*number*\n\nA current length of a collection.\n\n### total\n\n*number*\n\nA total number of records in the backend.\n\n### offset\n\n*number*\n\nA current offset (for pagination).\n\n### maxSize\n\n*number*\n\nA max size to fetch (for pagination).\n\n### where\n\n*Object*\n\nA where clause.\n\n## Instantiating\n\nWith a factory:\n\n```js\n\nexport default class extends View {\n\n    setup() {\n        this.wait(this.loadCollection());\n    }\n\n    async loadCollection() {\n        this.collection = await this.getCollectionFactory().create('Account');\n\n        await this.collection.fetch();\n    }\n}\n```\n\nWithout factory:\n\n```js\nimport View from 'view';\nimport Collection from 'collection';\n\nexport default class extends View {\n\n    setup() {\n        const collection = new Collection();\n        // The URL will be used when fetching from the backend.\n        collection.url = 'MyEntityType/someEndPoint'; \n\n        this.wait(\n            collection.fetch()\n        );\n    }\n}\n```\n\n## Events\n\nNote: `listenTo` and `listenToOnce` are methods of the *view* class.\n\n### sync\n\nOnce a collection is fetched.\n\n```js\nthis.listenTo(collection, 'sync', (collection, response, options) => {});\n```\n\n### update\n\nOnce a collection is updated.\n"
  },
  {
    "path": "docs/development/confirm-dialog.md",
    "content": "# Confirmation dialog\n\nShowing a confirmation modal dialog to a user before doing some actions.\n\nAvailable in views.\n\n```js\n    this.confirm({\n        message: this.translate('someMessageName', 'messages'),\n        confirmText: this.translate('Confirm'), // text of the confirmation button\n    }).then(() => {\n        // here do some actions\n    });\n```\n"
  },
  {
    "path": "docs/development/container-services.md",
    "content": "# Container Services\n\nConsole command that prints all available container services with their implementing classes:\n\n```\nbin/command app-info --container\n```\n\nMost often used services are listed below.\n\n## entityManager\n\nClass: `Espo\\ORM\\EntityManager`\n\nA central access point to [ORM](orm.md) functionality.\n\n## metadata\n\nClass: `Espo\\Core\\Utils\\Metadata`\n\nApplication [metadata](metadata.md).\n\n## config\n\nClass: `Espo\\Core\\Utils\\Config`\n\nA main application config.\n\n## ormDefs\n\n*As of v7.0.*\n\nClass: `Espo\\ORM\\Defs\\Defs`\n\nEntity definitions (fields, attributes, relations).\n\n## fileManager\n\nClass: `Espo\\Core\\Utils\\File\\Manager`\n\nProvides functions for reading and storing files.\n\n## applicationState\n\nClass: `Espo\\Core\\ApplicationState`\n\nProvides information about an application, current user, portal.\n\n## log\n\nClass: `Espo\\Core\\Utils\\Log`\n\nA logger. Messages are written into `data/log`.\n\n## user\n\nClass: `Espo\\Entities\\User`\n\nA current user. If an application does not require an authentication, then the *system* user is substituted.\n\n## preferences\n\nClass: `Espo\\Entities\\Preferences`\n\nPreferences of a current user.\n\n## aclManager\n\nClass: `Espo\\Core\\AclManager`\n\nProvides access checking functions for any user.\n\n## acl\n\nClass: `Espo\\Core\\Acl`\n\nProvides access checking functions for a current user. A wrapper for *aclManager*.\n\n## fieldUtil\n\nClass: `Espo\\Core\\Utils\\FieldUtil`\n\nAn utility class for obtaining information about fields.\n\n## dateTime\n\nClass: `Espo\\Core\\Utils\\DateTime`\n\nDate-time utility functions.\n\n## number\n\nClass: `Espo\\Core\\Utils\\NumberUtil`\n\nNumber utility functions.\n\n## fileStorageManager\n\nClass: `Espo\\Core\\FileStorage\\Manager`\n\nStores and reads attachment entities.\n\n## language\n\nClass: `Espo\\Core\\Utils\\Language`\n\nLanguage util of a current user.\n\n## defaultLanguage\n\nClass: `Espo\\Core\\Utils\\Language`\n\nA util for a default language of the system.\n\n## baseLanguage\n\nClass: `Espo\\Core\\Utils\\Language`\n\nA util for *en_US* language.\n\n## formulaManager\n\nClass: `Espo\\Core\\Formula\\Manager`\n\nTo run Formula scripts.\n\n## streamService\n\nClass: `Espo\\Tools\\Stream\\Service`\n\n## applicationConfig\n\n*As of v9.1.*\n\nClass: `Espo\\Core\\Utils\\Config\\ApplicationConfig`\n\n## systemConfig\n\n*As of v9.1.*\n\nClass: `Espo\\Core\\Utils\\Config\\SystemConfig`\n\n## session\n\n*As of v10.0.*\n\nInterface: `Espo\\Core\\Session\\Session`\n"
  },
  {
    "path": "docs/development/custom-buttons.md",
    "content": "# Custom buttons & dropdown actions for detail, list, edit views\n\n## In top-right corner\n\nHow to add buttons (or dropdown actions) that will appear in the top-right corner.\n\nAn example for the detail view of the *Lead* entity type.\n\n### Definition\n\nCreate a file (if it doesn't exist) `custom/Espo/Custom/Resources/metadata/clientDefs/Lead.json`:\n\n```json\n{\n    \"menu\": {\n        \"detail\": {\n            \"buttons\": [\n                \"__APPEND__\",\n                {\n                    \"label\": \"My Action\",\n                    \"name\": \"myAction\",\n                    \"style\": \"default\",\n                    \"acl\": \"edit\",\n                    \"aclScope\": \"Lead\",\n                    \"handler\": \"custom:my-action-handler\",\n                    \"initFunction\": \"initMyAction\",\n                    \"actionFunction\": \"myAction\",\n                    \"checkVisibilityFunction\": \"isMyActionVisible\"\n                }\n            ]\n        }\n    }\n}\n```\n\nParameters:\n\n* `name` – A name. Mandatory if a handler is used.\n* `handler` – A handler.\n* `initFunction` – A handler method to run on initialization. Omit if not needed. \n* `acl` – Defines what access level is required to see the button. You can omit this parameter.\n* `aclScope` – What scope to check access to. If omitted, the current scope is used.\n* `checkVisibilityFunction` – A handler method that will be used to determine whether an item is visible. The method should return a boolean value. As of v8.1.\n* `iconClass` – An icon class name.\n* `labelTranslation` – A label translation path. Alternative to *label*.\n* `actionFunction` – An action method in the handler. As of v8.1.\n* `index` – A position index. Supported only for buttons. Use negative values to add to the beginning. As of 9.4.\n\nIn order to add dropdown action, you need to use the `dropdown` key instead of *buttons*.\n\nAvailable *style* values:\n\n* `default`\n* `success`\n* `danger`\n* `warning`\n* `text` (as of v10.0)\n\nIn the parameter `accessDataList`, it's possible to define rules that determine whether an action item is visible to a user. See the `module:utils~AccessDefs` JSDoc type in the [source file](https://github.com/espocrm/espocrm/blob/master/client/src/utils.js).\n\nThe parameter `labelTranslation` defines a label translation path. Useful if you don't want to incorporate a new label but use an existing one. Example: `Global.scopeNamesPlural.Opportunity`. \n\nMenu items defined in the `Global.json` file will be applied for all entity types.\n\nAvailable views (object keys in definitions):\n\n* detail\n* edit\n* list\n\n### Handler class\n\nCreate a file `client/custom/src/my-action-handler.js`:\n\n```js\ndefine(['action-handler'], (Dep) => {\n\n    return class extends Dep {\n\n        initMyAction() {}\n\n        async myAction() {\n            this.view.disableMenuItem('myAction');\n\n            let response;\n\n            try {\n                response = await Espo.Ajax.getRequest('Lead/' + this.view.model.id);\n            } catch (e) {\n                this.view.enableMenuItem('myAction');\n\n                return;\n            }\n\n            console.log(response);\n\n            this.view.enableMenuItem('myAction');\n        }       \n\n        isMyActionVisible() {\n            return !['Converted', 'Dead', 'Recycled'].includes(this.view.model.attributes.status);\n        }\n    }\n});\n```\n\n## Dropdown action in detail view\n\nAn action item next to the edit button.\n\nAn example for the *Lead* entity type. Menu items defined in the `Global.json` file will be applied for all entity types.\n\n### Definition\n\nCreate a file (if it doesn't exist) `custom/Espo/Custom/Resources/metadata/clientDefs/Lead.json`:\n\n```json\n{\n    \"detailActionList\": [\n        \"__APPEND__\",\n        {\n            \"label\": \"Test Action\",\n            \"name\": \"test\",\n            \"acl\": \"edit\",\n            \"handler\": \"custom:my-action-handler\",\n            \"initFunction\": \"initTest\",\n            \"checkVisibilityFunction\": \"isTestVisible\",\n            \"actionFunction\": \"test\"\n        }\n    ]\n}\n```\n\nParameters:\n\n* `name` ~ A name. Important if a handler is used.\n* `handler` – A handler.\n* `initFunction` – A handler method to run on initialization. Omit if not needed. \n* `acl` – Defines what access level is required to see the button. You can omit this parameter.\n* `checkVisibilityFunction` – A handler method that will be used to determine whether an item is visible. The method should return a boolean value. As of v8.1.\n* `actionFunction` – An action method in the handler. As of v8.1.\n\n### Handler class\n\nCreate a file `client/custom/src/my-action-handler.js`:\n\n```js\ndefine(['action-handler'], (Dep) => {\n\n   return class extends Dep {\n\n        initTest() {}\n\n        async test() {\n            const response = await Espo.Ajax.getRequest('Lead/' + this.view.model.id);\n\n            console.log(response);\n        }       \n\n        isTestVisible() {\n            return !['Converted', 'Dead', 'Recycled'].includes(this.view.model.attributes.status);\n        }\n    }\n});\n```\n\n## Dropdown action in detail modal view\n\n*As of v7.2.*\n\nEverything is the same as for the detail view. The only difference is that the metadata parameter name is `modalDetailActionList`.\n\n## Mass action in list view\n\nAn action will available in the *Actions* dropdown when you select records on the list view.\n\n*As of v7.0.*\n\nAn example for *Meeting* entity type.\n\nCreate a file (if it doesn't exist) `custom/Espo/Custom/Resources/metadata/clientDefs/Meeting.json`:\n\n```json\n{\n    \"massActionList\": [\n        \"__APPEND__\",\n        \"test\"\n    ],\n    \"checkAllResultMassActionList\": [\n        \"__APPEND__\",\n        \"test\"\n    ],\n    \"massActionDefs\": {\n        \"test\": {\n            \"handler\": \"custom:test-handler\",\n            \"initFunction\": \"initTest\",\n            \"actionFunction\": \"test\"\n        }\n    }\n}\n```\n\nCreate a handler `client/custom/src/test-handler.js`:\n\n```js\ndefine('custom:test-handler', [], () => {\n\n    return class {\n\n        constructor(view) {\n            this.view = view;\n        }\n\n        initTest() {\n            // called when the list view is loaded\n\n            // here you can remove the action on a specific condition\n            // this.view.removeMassAction('test');\n            \n            // const acl = this.view.getAcl();\n            // const currentUser = this.view.getUser();\n        }\n\n        /**\n         * @param {{entityType: string, action: string, params: Record}} data\n         */\n        test(data) {           \n            // Here you can show a modal or send an ajax request.\n            // this.view.createView( ... )\n            // Espo.Ajax.postRequest( ...)\n        }\n    }\n});\n\n```\n\nCreate a language file `custom/Espo/Custom/Resources/i18n/en_US/Meeting.json`:\n\n```json\n{\n    \"massActions\": {\n        \"test\": \"Test\"\n    }\n}\n```\n\nClear cache.\n\nYou can use *Mass Action* framework to handle mass actions in the back-end. Available as of v7.0. Send a POST request to the `MassAction` endpoint with data passed to the action method.\n\n## See more\n\nIn Advanced Pack it's possible to create detail view buttons and dropdown items that run workflow actions. A button can be configured to be visible only if specific conditions are met.\n"
  },
  {
    "path": "docs/development/custom-config-parameters.md",
    "content": "# Custom config parameters\n\nIn this article it will be shown how to add custom config parameters and how to make them available on the administration panel.\n\nIn the example it's supposed that your module is named `MyModule`. Replace `MyModule` and `my-module` with your real module name.\n\n### 1. Metadata entityDefs > settings\n\nCreate a file `custom/Espo/Modules/MyModule/Resources/metadata/entityDefs/Settings.json`:\n\n```json\n{\n    \"fields\": {\n        \"myParameter\": {\n            \"type\": \"enum\",\n            \"options\": [\"Option 1\", \"Option 2\"],\n            \"tooltip\": true\n        }\n    }\n}\n```\n\n### 2. Metadata app > config\n\nCreate a file `custom/Espo/Modules/MyModule/Resources/metadata/app/config.json`:\n\n```json\n{\n    \"params\": {\n        \"myParameter\": {\n            \"level\": \"admin\"\n        }\n    }\n}\n```\n\nThe *level* parameter defines availability of the config parameter in the front-end.\n\n* `default` –  available for logged-in users (applied by default);\n* `global` – available even before logging in;\n* `system` – never available;\n* `internal` – never available for read, admin can write (useful for passwords, secrets; recommended to use the *password* field type) (as of v7.3);\n* `admin` – available only for admin (read and write);\n* `superAdmin` – available only for super-admin (read and write).\n\nThe *readOnly* [parameter](metadata/app-config.md#readonly) disables the ability to change a parameter value for admin users. \n\n### 3. Metadata app > adminPanel\n\nCreate a file `custom/Espo/Modules/MyModule/Resources/metadata/app/adminPanel.json`:\n\n```json\n{\n    \"myPanel\": {\n        \"label\": \"My Panel\",\n        \"itemList\": [\n            {\n                \"url\": \"#Admin/mySettings\",\n                \"label\": \"My Settings\",\n                \"iconClass\": \"fas fa-cog\",\n                \"description\": \"myDescription\",\n                \"recordView\": \"modules/my-module/views/admin/my-settings\"\n            }\n        ],\n        \"order\": 101\n    }\n}\n```\n\n### 4. Language files\n\nCreate a file `custom/Espo/Modules/MyModule/Resources/i18n/en_US/Admin.json`:\n\n```json\n{\n    \"keywords\": {\n        \"myPanel\": \"some search keyword,another search keyword\"\n    },\n    \"descriptions\": {\n        \"myDescription\": \"Description text.\"\n    },\n    \"labels\": {\n        \"My Settings\": \"My Settings\",\n        \"My Panel\": \"My Panel\"\n    }\n}\n```\n\n\nCreate a file `custom/Espo/Modules/MyModule/Resources/i18n/en_US/Settings.json`:\n\n```json\n{\n    \"fields\": {\n        \"myParameter\": \"My Parameter\"\n    },\n    \"tooltips\": {\n        \"myParameter\": \"My parameter tooltip text. Markdown supported.\"\n    },\n    \"options\": {\n        \"myParameter\": {\n            \"Option 1\": \"Option 1\",\n            \"Option 2\": \"Option 2\"\n        }\n    }\n}\n```\n\n### 5. View\n\nCreate a file `client/custom/modules/my-module/src/views/admin/my-settings.js`:\n\n```js\ndefine(['views/settings/record/edit'], (Dep) => {\n\n    return class extends Dep {\n\n        detailLayout = [\n            {\n                rows: [\n                    [\n                        {\n                            name: 'myParameter',\n                        },\n                        false,\n                    ],\n                ]\n            }\n        ]\n\n        // Dynamic logic can de defined.\n        dynamicLogicDefs: {}\n\n        setup() {\n            super.setup();\n            \n            // Some custom logic can be written here.\n        }\n    }\n});\n```\n\n### 6. Final step\n\nClear cache.\n\nThe parameter value now can be read in the back-end:\n\n```php\n<?php\n/** @var \\Espo\\Core\\Utils\\Config $config */\n$config->get('myParameter');\n```\n"
  },
  {
    "path": "docs/development/custom-css.md",
    "content": "# Custom CSS file\n\nCreate a file `custom/Espo/Custom/Resources/metadata/app/client.json`.\n\n```json\n{\n    \"cssList\": [\n        \"__APPEND__\",\n        \"path/to/your/file.css\"\n    ]\n}\n```\n\nMake sure the CSS file is readable by the webserver. It's recommended to put it in `client/custom/css` or `client/custom/modules/{module-name}/css` directory. \n\nThen clear cache.\n"
  },
  {
    "path": "docs/development/custom-entity-type.md",
    "content": "# Custom Entity Type\n\nThis article gives information about how to create custom entity types manually (without using the UI).\n\nIn the example, the entity type will be defined in the `custom/Espo/Modules/MyModule` directory which corresponds to the `Espo\\Modules\\MyModule` namespace. You can also define in `custom/Espo/Custom` directory which corresponds to the `Espo\\Custom` namespace.\n\nThe entity type name created in the example is `MyEntity`.\n\nAfter all needed files are created, you need to run rebuild (Administration > Rebuild). It will clear cache and create the database table.\n\n## Metadata\n\n### entityDefs\n\n[Reference](metadata/entity-defs.md)\n\nFile: `custom/Espo/Modules/MyModule/Resources/metadata/entityDefs/MyEntity.json`\n\nDefines entity definitions: fields, links, indexes and parameters.\n\nExample:\n\n```json\n{\n    \"fields\": {\n        \"name\": {\n            \"type\": \"varchar\",\n            \"maxLength\": 100,\n            \"required\": true\n        },\n        \"status\": {\n            \"type\": \"enum\",\n            \"maxLength\": 9,\n            \"options\": [\n                \"Draft\",\n                \"Started\",\n                \"Completed\",\n                \"Canceled\"\n            ],\n            \"default\": \"Draft\",\n            \"style\": {\n                \"Started\": \"primary\",\n                \"Completed\": \"success\",\n                \"Canceled\": \"info\"\n            }\n        },\n        \"assignedUser\": {\n            \"type\": \"link\"\n        },\n        \"teams\": {\n            \"type\": \"linkMultiple\"\n        },\n        \"createdAt\": {\n            \"type\": \"datetime\",\n            \"readOnly\": true\n        }\n    },\n    \"links\": {\n        \"assignedUser\": {\n            \"type\": \"belongsTo\",\n            \"entity\": \"User\"\n        },\n        \"teams\": {\n            \"type\": \"hasMany\",\n            \"entity\": \"Team\",\n            \"relationName\": \"entityTeam\"\n        }\n    },\n    \"indexes\": {\n        \"name\": {\n            \"columns\": [\"name\"]\n        }\n    },\n    \"collection\": {\n        \"textFilterFields\": [\"name\"],\n        \"orderBy\": \"createdAt\",\n        \"order\": \"desc\"\n    }\n}\n```\n\n### scopes\n\n[Reference](metadata/scopes.md)\n\nFile: `custom/Espo/Modules/MyModule/Resources/metadata/scopes/MyEntity.json`\n\nDefines scope parameters.\n\nExample:\n\n```json\n{\n    \"module\": \"MyModule\",\n    \"entity\": true,\n    \"object\": true,\n    \"acl\": true,\n    \"tab\": true,\n    \"importable\": true\n}\n```\n\n### clientDefs\n\n[Reference](metadata/client-defs.md)\n\nFile: `custom/Espo/Modules/MyModule/Resources/metadata/clientDefs/MyEntity.json`\n\nDefines entity type parameters for the frontend.\n\nExample:\n\n```json\n{\n    \"controller\": \"controllers/record\"\n}\n```\n\nWithout the *controller* parameter the entity type won't be available in the frontend. *controllers/record* is a build-in standard CRUD controller in the frontend.\n\n## Entity class\n\nFile: `custom/Espo/Modules/MyModule/Entities/MyEntity.php`\n\nExample:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule\\Entities;\n\nuse Espo\\Core\\ORM\\Entity;\nuse Espo\\Core\\Field\\LinkMultiple;\nuse Espo\\Core\\Field\\DateTime;\n\nclass MyEntity extends Entity\n{\n    // Highly recommended to define the name in the ENTITY_TYPE constant.\n    public const ENTITY_TYPE = 'MyEntity';\n\n    // Not necessary but may be useful for business logic code.\n    public const STATUS_DRAFT = 'Draft';\n    public const STATUS_STARTED = 'Started';\n    public const STATUS_COMPLETED = 'Completed';\n    public const STATUS_CANCELED = 'Canceled';\n\n    // Getter and setters are not necessary\n    // but may be useful for business logic code.\n\n    public function getName(): string\n    {\n        return $this->get('name');\n    }\n\n    public function setName(string $name): self\n    {\n        $this->set('name', $name);\n\n        return $this;\n    }\n\n    public function getStatus(): string\n    {\n        return $this->get('status');\n    }\n\n    public function setStatus(string $status): self\n    {\n        $this->set('status', $status);\n\n        return $this;\n    }\n\n    public function getAssignedUserId(): ?string\n    {\n        $this->get('assignedUserId');\n\n        return $this;\n    }\n\n    public function setAssignedUserId(?string $assignedUserId): self\n    {\n        $this->set('assignedUserId', $assignedUserId);\n\n        return $this;\n    }\n\n    public function getTeams(): LinkMultiple\n    {\n        /** @var LinkMultiple */\n        return $this->getValueObject('teams');\n    }\n\n    public function setTeams(LinkMultiple $teams): self\n    {\n        $this->setValueObject('teams', $teams);\n\n        return $this;\n    }\n\n    public function getCreatedAt(): DateTime\n    {\n        /** @var DateTime */\n        return $this->getValueObject('createdAt');\n    }\n}\n```\n\n## Controller class\n\nFile: `custom/Espo/Modules/MyModule/Controllers/MyEntity.php`\n\nA Controller class is needed if you need to have CRUD operations available via the API. That includes the frontend, as the frontend communicates with the backend via the API.\n\nExample:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule\\Controllers;\n\nuse Espo\\Core\\Controllers\\Record;\n\n// Just extend the standard CRUD controller.\n// No more methods are needed.\nclass MyEntity extends Record\n{}\n```\n\n## Layouts\n\nLocation: `custom/Espo/Modules/MyModule/Resources/layouts/MyEntity`\n\n### detail\n\nFile: `custom/Espo/Modules/MyModule/Resources/layouts/MyEntity/detail.json`\n\nExample:\n\n```json\n[\n    {\n        \"rows\": [\n            [\n                {\"name\": \"name\"}, {\"name\": \"status\"}\n            ]\n        ]\n    },\n]\n```\n\nThe same for *detailSmall.json*.\n\n### list\n\nFile: `custom/Espo/Modules/MyModule/Resources/layouts/MyEntity/list.json`\n\nExample:\n\n```json\n[\n    {\"name\": \"name\", \"link\": true},\n    {\"name\": \"status\", \"width\": 40}\n]\n```\n\nThe same for *listSmall.json*.\n\n### filters\n\nFile: `custom/Espo/Modules/MyModule/Resources/layouts/MyEntity/filters.json`\n\nExample:\n\n```json\n[\n    \"status\",\n    \"assignedUser\",\n    \"teams\"\n]\n```\n\n## Translations\n\n### Global\n\nFile: `custom/Espo/Modules/MyModule/Resources/i18n/en_US/Global.json`\n\n```json\n{\n    \"scopeNames\": {\n        \"MyEntity\": \"My Entity\"\n    },\n    \"scopeNamesPlural\": {\n        \"MyEntity\": \"My Entities\"\n    }\n}\n```\n\n### Entity\n\nFile: `custom/Espo/Modules/MyModule/Resources/i18n/en_US/MyEntity.json`\n\n```json\n{\n    \"labels\": {\n        \"Create MyEntity\": \"Create My Entity\"\n    },\n    \"fields\": {\n        \"name\": \"Name\",\n        \"status\": \"Status\",\n        \"assignedUser\": \"Assigned User\",\n        \"teams\": \"Teams\",\n        \"createdAt\": \"Created At\"\n    },\n    \"links\": {\n        \"assignedUser\": \"Assigned User\",\n        \"teams\": \"Teams\"\n    },\n    \"options\": {\n        \"status\": {\n            \"Draft\": \"Draft\",\n            \"Started\": \"Started\",\n            \"Completed\": \"Completed\",\n            \"Canceled\": \"Canceled\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/custom-field-type.md",
    "content": "# Creating custom field type\n\nUse the name of your field type instead of `{field-type}`.\n\n### Field definition\n\nCreate a file `custom/Espo/Custom/Resources/metadata/fields/{field-type}.json` with needed parameters.\n\n```json\n{\n   \"view\": \"custom:views/fields/{field-type}\"\n}\n```\n\nUse out-of-the-box field types as examples: `application/Espo/Resources/metadata/fields`.\n \n### View\n\nCreate a file `client/custom/src/views/fields/{field-type}.js`:\n\n```js\ndefine(['views/fields/base'], (BaseFieldView) => {\n    \n    return class extends BaseFieldView {\n\n        // Templates for all view modes.\n        detailTemplateContent = ` ... `\n        listTemplateContent = ` ... `\n        editTemplateContent = ` ... ` \n        searchTemplateContent = ` ... `\n        \n        setup() {}\n    }\n});\n```\n\nSee out-of-the-box field types for examples:\n\n* `client/src/views/fields/` — views\n\n### Translation\n\nThe label is used in Entity Manager can be set in `custom/Espo/Custom/Resources/i18n/en_US/Admin.json` in the section `fieldTypes`.\nIf you need to add translation to other language, use [language code](https://en.wikipedia.org/wiki/ISO_639-1)_[Country Code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) instead of `en_US`.\n\nThen you need to clear cache at the administration panel.\n\n### Backend validator\n\nYou can define a validator class in a field metadata file in the `validatorClassName` parameter. See the [barcode field](https://github.com/espocrm/espocrm/blob/stable/application/Espo/Resources/metadata/fields/barcode.json) as an example.\n"
  },
  {
    "path": "docs/development/custom-views.md",
    "content": "# Custom views\n\n## Record views\n\nEspoCRM framework provides abilities to define custom views for certain entity types. They must be defined in `clientDefs` category of metadata.\n\n`custom/Espo/Custom/Resources/metadata/clientDefs/YourEntityType.json`\n\n```json\n{\n    \"views\": {\n        \"list\": \"custom:views/your-entity-type/list\",\n        \"detail\": \"custom:views/your-entity-type/detail\",\n        \"edit\": \"custom:views/your-entity-type/edit\"\n    },\n    \"recordViews\": {\n        \"list\": \"custom:views/your-entity-type/record/list\",\n        \"detail\": \"custom:views/your-entity-type/record/detail\",\n        \"edit\": \"custom:views/your-entity-type/record/edit\"\n    }\n}\n```\n\n### Detail view\n\n`client/custom/src/views/your-entity-type/record/detail.js`\n\nThe view 'views/record/detail' contains all panels with fields, relations and other data you can see on detail view. It doesn't contain header and buttons in the top-right corner.\n\n```javascript\ndefine('custom:views/your-entity-type/record/detail', ['views/record/detail'], (DetailRecordView) => {\n\n    return class extends DetailRecordView {\n\n        // custom template, omit if you don't need it\n        // template = 'custom:your-entity-type/record/detail'\n        \n        // custom central view, omit if you don't need it\n        // middleView = 'custom:views/your-entity-type/record/detail-middle'\n        \n        // custom side column view, omit if you don't need it\n        // sideView = 'custom:views/your-entity-type/record/detail-side'\n        \n        // custom bottom view, omit if you don't need it\n        // bottomView = 'custom:views/your-entity-type/record/detail-bottom'\n\n        setup() {\n            super.setup();\n\n            this.hideField('someField');\n            this.showField('someField');\n\n            // custom initialization logic, like binding listening to model changes\n            this.listenTo(this.model, 'change:myField', () => {\n                this.model.set('anotherField', this.model.get('myField') + ' Hello');\n\n                this.hideField('someField');\n                this.showField('someField');\n                this.setFieldRequired('someField');\n                this.setFieldNotRequired('someField');\n\n                this.setFieldReadOnly('someField');\n                this.setFieldNotReadOnly('someField');\n\n                this.hidePanel('activities');\n                this.showPanel('history');\n            });\n        }\n\n        afterRender() {\n            super.afterRender();\n        }\n    }\n});\n\n```\n\nYou are able to create a custom template with the following path: `client/custom/res/templates/your-entity-type/record/detail.tpl`\n\n`client/custom/src/views/your-entity-type/detail.js`\n\nDetail view contains a record view and header view.\n\n### Edit view\n\n`client/custom/src/views/your-entity-type/edit.js`\n`client/custom/src/views/your-entity-type/record/edit.js`\n\nThe same as detail but it is used when record is being created or edited not in inline-edit mode.\n\n### List view\n\n`client/custom/src/views/your-entity-type/list.js`\n\nList view contains Record/List view, Header and Search Form View.\n\n`client/custom/src/views/your-entity-type/record/list.js`\n\nThe views 'views/list/record' contains rows of records.\n\n### Extending from specific view\n\nIt's worth to mention that you need to inherit your view class from specific class for your entity if one already exists.\n\n```javascript\ndefine('custom:views/email/record/detail', ['views/email/record/detail'], (EmailDetailRecordView) => {\n    return class extends EmailDetailRecordView {}\n});\n```\n\n## Field views\n\nCustom views for specific fields should be specified in entityDefs section of metadata.\n\nExample for Address field of Account entity type.\n\n`custom/Espo/Custom/Resources/metadata/entityDefs/Account.json`\n\n\n```json\n{\n    \"fields\": {\n        \"address\": {\n            \"view\": \"custom:views/account/fields/address\"\n        }  \n    }\n}\n```\n\n`client/custom/src/views/account/fields/address.js`\n\n```js\ndefine('custom:views/fields/address', ['views/fields/address'], (AddressFieldView) => {\n\n   return class extends AddressFieldView {\n  \n        setup() {\n            super.setup();\n            // some initialization\n        }\n\n        afterRender() {\n            super.afterRender();\n            // your customizations executed after the field is rendered\n        }\n    }\n});\n```\n\n## See also\n\n* [View setup handlers](frontend/view-setup-handlers.md)\n"
  },
  {
    "path": "docs/development/customize-standard-fields.md",
    "content": "# Customizing existing fields\n\n## Customizing field type\n\nAn example for the *Address* field type.\n\nCreate a file `custom/Espo/Custom/Resources/metadata/fields/address.json`.\n\n```json\n{\n    \"view\": \"custom:views/fields/address\"\n}\n```\n\nCreate a file `client/custom/src/views/fields/address.js`.\n\n```js\ndefine(['views/fields/address'], (AddressFieldView) => {\n\n   return class extends AddressFieldView {\n\n        //detailTemplateContent = ' ... '\n        //editTemplateContent = ' ... '\n        //listTemplateContent = ' ... '\n        //listLinkTemplateContent = ' .. '\n  \n        setup() {\n            super.setup();\n        }\n\n        afterRender() {\n            super.afterRender();\n            // your customizations executed after the field is rendered\n        }\n    }\n});\n```\n\nCreate a template file (if needed) `client/custom/res/templates/fields/address/detail.tpl`.\n\n## Customizing specific field\n\n### Changing field type of existing field\n\nAn example for the *Meeting*'s *Name* field.\n\nCreate (or edit if exists) a file `custom/Espo/Custom/Resources/metadata/entityDefs/Meeting.json`.\n\n```json\n{\n    \"fields\": {\n        \"name\": {\n            \"type\": \"enum\"\n        }\n    }\n}\n```\n\n### Custom view for specific field\n\nAn example for the *Meeting*'s *Name* field.\n\nCreate (or edit if exists) a file `custom/Espo/Custom/Resources/metadata/entityDefs/Meeting.json`.\n\n```json\n{\n    \"fields\": {\n        \"name\": {\n            \"view\": \"custom:views/meeting/fields/name.js\"\n        }\n    }\n}\n```\n\nFile `client/custom/src/views/meeting/fields/name.js`:\n\n```js\ndefine(['views/fields/varchar'], (VarcharFieldView) => {\n\n   return class extends VarcharFieldView {\n  \n        setup() {\n            super.setup();\n            // some initialization\n        }\n\n        afterRender() {\n            super.afterRender();\n            // your customizations executed after the field is rendered\n        }\n    }\n});\n```\n"
  },
  {
    "path": "docs/development/db-indexes.md",
    "content": "# Database indexes\n\nProper database indexes can drastically improve a performance of list view loading, reports, search operations etc.\n\nAfter changes you need to rebuild database. It's better to do from CLI to avoid timeout issue.\n\nCommand to run rebuild:\n\n```\nphp rebuild.php\n```\n\n## Defining indexes\n\nIndexes are defined in metadata > entityDefs.\n\n### Example\n\nFor *Lead* entity type.\n\n`custom/Espo/Custom/Resources/metadata/entityDefs/Lead.json`:\n\n\n```json\n{\n    \"indexes\": {\n        \"myIndexNameOne\": {\n            \"columns\": [\"columnName\"]   \n        },\n        \"myIndexNameTwo\": {\n            \"columns\": [\"columnNameOne\", \"columnNameTwo\"]  \n        },\n        \"myUniqueIndexName\": {\n            \"type\": \"unique\",\n            \"columns\": [\"id\", \"columnNameOne\", \"columnNameTwo\"]  \n        }\n    }\n}\n```\n\nNote: Column names should be in camel case.\n\nYou need to run rebuild after changes.\n\n## Forcing index usage in ORM\n\nYou need to specify an index name in *useIndex* param.\n\n```php\n<?php\n$query = $entityManager->getQueryBuilder()\n    ->select()\n    ->from($entityType)    \n    ->where($whereClause)\n    ->useIndex('myIndexNameOne')\n    ->build();\n    \n$collection = $entityManager->getRDBRepository($entityType)\n    ->clone($query)\n    ->find();\n```\n\n## Relationship table indexes\n\nIn entityDefs:\n\n```json\n{\n    \"links\": {\n        \"linkName\": {\n            \"additionalColumns\": {\n                \"role\": {\n                    \"type\": \"varchar\"\n                }\n            },\n            \"indexes\": {\n                \"role\": {\n                    \"columns\": [\"role\"]\n                }\n            }\n        }\n    }\n}    \n```\n"
  },
  {
    "path": "docs/development/di.md",
    "content": "# Dependency Injection\n\nThe Dependency Injection framework provides needed dependencies to classes (usually via a constructor). For example, if your hook needs the EntityManager service, you just  define it as a constructor parameter.\n\nFor example, your controller has a dependency on some service class. That service class has other dependencies (e.g. the entity manager, some utility classes), these dependencies can have their own dependencies and so on. You don't need to instantiate dependencies, you just define them in class constructors and the framework provides them automatically.\n\n```\n- MyController\n    - MyService\n        - EntityManager (container service)\n        - MyUtilityClass1\n            - EntityManager (container service)\n            - FileStorageManager (container service)\n        - MyUtilityClass2\n```\n\nIn this article:\n\n* [Container services](#container-services)\n* [Injectable factory](#injectable-factory)\n* [Binding](#binding)\n* [See also](#see-also)\n\nThere are two classes responsible for the dependency injection in EspoCRM:\n\n* Container – `Espo\\Core\\Container` [class](https://github.com/espocrm/espocrm/blob/master/application/Espo/Core/Container.php);\n* InjectableFactory – `Espo\\Core\\InjectableFactory` [class](https://github.com/espocrm/espocrm/blob/master/application/Espo/Core/InjectableFactory.php).\n\n## Container services\n\nThe Container contains services. These services are supposed to be used in multiple places throughout the system. **Lazy initialization** is used, meaning that a service is not loaded until it's asked (as a dependency).\n\nContainer services are defined:\n\n* in [metadata](metadata.md) (app > containerServices);\n* by loader classes (in `Espo\\Core\\Loaders` namespace);\n\n!!! note\n\n    The best practice is not to require the *container* in your classes, and never use it directly. A specific service can be required in a constructor or with Aware interface.\n\nConsole command that prints all available container services with their implementation classes:\n\n```\nbin/command app-info --container\n```\n\nMost used container services are listed [here](container-services.md).\n\n### Defining\n\nIf you need to define your custom container services, do it in metadata. In your module or in the custom folder:\n\n* `custom/Espo/Modules/{YourModule}/Resources/metadata/app/containerServices.json`;\n* `custom/Espo/Custom/Resources/metadata/app/containerServices.json`.\n\nWhen defining in metadata there are 2 options:\n\n* specify a class for a service;\n* specify a loader that loads a service (the loader should implement `Espo\\Core\\Container\\Loader` interface).\n\nA definition example:\n\n```json\n{\n    \"myService1\": {\n        \"className\": \"Espo\\\\Modules\\\\MyModule\\\\MyService1\"\n    },\n    \"myService2\": {\n        \"loaderClassName\": \"Espo\\\\Modules\\\\MyModule\\\\MyService2Loader\"\n    }\n}\n```\n\nThen you need to bind a class name to the service.\n\nFile `custom/Espo/Modules/MyModule/Binding.php`:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule;\n\nuse Espo\\Core\\Binding\\BindingProcessor;\nuse Espo\\Core\\Binding\\Binder;\n\nclass Binding implements BindingProcessor\n{\n    public function process(Binder $binder): void\n    {\n        $binder->bindService('Espo\\\\Modules\\\\MyModule\\\\MyService1', 'myService1');\n    }\n}\n```\n\nNeeded dependencies will be passed to a class constructor upon instantiation. Parameter type hinting and binding (processed on application start) will be used (via reflection) to detect dependencies.\n\nExample:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule;\n\nuse Espo\\ORM\\EntityManager;\n\nclass MyService1\n{\n    public function __construct(private EntityManager $entityManager) {}\n}\n```\n\n## Injectable factory\n\nThe Injectable Factory is a core class that creates objects resolving and injecting needed dependencies. Controllers, Entry Points, Hooks etc. – all are created by the Injectable Factory (automatically by the framework).\n\nThe Injectable Factory is available as a service in the Container. That means that *injectableFactory* can be required as a dependency to be used directly.\n\nRequiring *injectableFactory* as a dependency:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule;\n\nuse Espo\\Core\\InjectableFactory;\nuse Espo\\Modules\\MyModule\\Something;\n\n/**\n * It's a good practice to use factory classes for creating instances of specific types.\n * Your class will require the factory rather than `injectableFactory` service.\n */\nclass SomeFactory\n{\n    public function __construct(\n        private InjectableFactory $injectableFactory,\n    ) {}\n\n    public function create(): Something\n    {\n        // Here can be logic that choose a specific class upon some criteria.\n        return $this->injectableFactory->create(Something::class);\n    }\n}\n```\n\n### Constructor injection\n\n*A recommended way.*\n\nBinding and constructor parameter names are used to detect service dependencies.\n\nResolving process:\n\n* Tries to resolve by binding (see below about binding); exits if success;\n* Tries to resolve by a parameter name, assuming that the parameter name matches the service name and the type hint matches the service class; exits if success;\n* Creates a new instance if the type hint is a class.\n\nIf a dependency is not a service, a new instance will be created every time the dependency is requested. See below.\n\n```php\n<?php\nnamespace Espo\\Custom;\n\nuse Espo\\ORM\\EntityManager;\nuse Espo\\Modules\\MyModule\\SomeClass;\n\nclass SomeClass\n{\n    /**\n     * EntityManager is a service. The same instance will be used for different classes.\n     * SomeClass is not a service. It will be instantiated every time.\n     */\n    public function __construct(\n        private EntityManager $entityManager,\n        private SomeClass $some,\n    ) {}\n}\n```\n\n### Setter method injection\n\n!!! warning\n\n    Not recommended. The setter injection mechanism was introduced for the ability to add dependencies to extended classes where it's not possible to change the constructor signature.\n\nCan be used along with the constructor injection. If a class implements *Aware* interface, the factory will use a corresponding setter function to inject a dependency. Setter traits can be utilized for adding setter functions into your class.\n\nExample:\n\n```php\n<?php\nnamespace Espo\\Custom;\n\nuse Espo\\Core\\Di;\n\nclass MyClass implements Di\\EntityManagerAware, Di\\MetadataAware\n{\n    use Di\\EntityManagerSetter;\n    use Di\\MetadataSetter;\n\n    public function someMethod(): void\n    {\n        // $this->entityManager;\n        // $this->metadata;\n    }\n}\n```\n\nUsing setter injections may be reasonable when you are extending from an existing class and want to add additional dependencies.\n\nLimitation: Only container services can be injected via setters.\n\n!!! note\n\n    It's not a recommended way to inject dependencies. Use it as a last resort if you don't want to modify an existing constructor signature.\n\n### Manual instantiating\n\nThis way is supposed to be utilized in factory classes.\n\n```php\n<?php\nuse Espo\\Custom\\SomeClass;\n\n$injectableFactory->create(SomeClass::class);\n```\n\nYou can specify constructor injections explicitly using *createdWith* method. Those that are not specified, will be tried to be resolved using *ReflectionClass*.\n\n```php\n<?php\n$injectableFactory->createWith($className, [\n    'parameterName1' => $value1,\n    'parameterName2' => $value2,\n]);\n```\n\nFactory example:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule;\n\nuse Espo\\Core\\InjectableFactory;\n\n/**\n * The factory instance is supposed to be passed as a dependency of some class.\n */\nclass SomeTypeFactory\n{\n    public function __construct(private InjectableFactory $injectableFactory) {}\n\n    /**\n     * The variable $userId will be used for the constructor parameter\n     * with the name 'userId'.\n     */\n    public function create(string $userId): SomeType\n    {\n        return $this->injectableFactory->createWith(SomeType::class, [\n            'userId' => $userId, \n        ]);\n    }    \n}\n```\n\nIt's also possible to pass a binding container when creating with the injectable factory. More info below.\n\n## Binding\n\nThere is the ability to bind interfaces to implementations and bind parameter names to specific values. Binding is used for resolving dependencies passed through a constructor.\n\nCustom binding can be set up in a `Binding` class of a module:\n\n* `Espo\\Modules\\{ModuleName}\\Binding`\n* `Espo\\Custom\\Binding`\n\n!!! note\n\n    The module order parameter is used when binding is processed. Meaning that modules with a lower order value will be processed first.\n\nCLI command to print all bindings:\n\n```\nbin/command app-info --binding\n```\n\nThe default binding is set up in `Espo\\Binding`.\n\n### Example\n\nFile `custom/Espo/Modules/MyModule/Binding.php`:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule;\n\nuse Espo\\Core\\Binding\\BindingProcessor;\nuse Espo\\Core\\Binding\\Binder;\n\nclass Binding implements BindingProcessor\n{\n    public function process(Binder $binder): void\n    {\n        $binder\n            ->bindService('Espo\\\\SomeServiceName', 'someServiceName')\n            ->bindImplementation('Espo\\\\SomeInterface', 'Espo\\\\SomeImplementation');\n\n        $binder\n            ->bindService('Espo\\\\SomeServiceName $name', 'anotherServiceName');\n       \n        $binder\n            ->for('Espo\\\\SomeClass')\n            ->bindImplementation('Espo\\\\SomeInterface', 'Espo\\\\SomeImplementation')\n            ->bindValue('$paramName', 'Some Value')\n            ->bindCallback(\n                 'Espo\\\\AnotherClass', \n                 // Callback arguments are resolved automatically.\n                 function (SomeDependency $dependency) {                     \n                     return $dependency->getSomething();\n                 }\n             );\n    }\n}\n```\n\nExplanation:\n\n* If any class requires `Espo\\SomeServiceName`, give the container service `someServiceName`.\n* If any class requires `Espo\\SomeInterface`, give an instance of `Espo\\SomeImplementation`.\n* If any class requires `Espo\\SomeServiceName ` and a parameter name is `$name`, then give `anotherServiceName` service.\n* When `Espo\\SomeClass` requires `Espo\\SomeInterface`, give an instance of `Espo\\SomeImplementation`.\n* When `Espo\\SomeClass` is instantiated, pass the value 'Same Value' for the parameter `$paramName`.\n* When `Espo\\SomeClass` is instantiated, use the callback to resolve a value of the parameter with the type `Espo\\AnotherClass`.\n\n### Binding to implementation\n\nBind an interface to a specific implementation.\n\n```php\n<?php\n$binder->bindImplementation(SomeInterface::class, SomeImplementation::class);\n```\n\n### Binding to service\n\nBind an interface to a specific [service](container-services.md).\n\n```php\n$binder->bindService(SomeInterface::class, 'someServiceName');\n```\n\n### Binding to factory\n\n*As of v7.0.*\n\nBind an interface to a specific factory so that a specific dependency will be created by a specific factory. The factory should implement `Espo\\Core\\Binding\\Factory` interface.\n\n```php\n<?php\n$binder->bindFactory(SomeInterface::class, SomeFactory::class);\n```\n\n### Binding to callback\n\nA callback will be used for creating a specific instance. The callback can have its own dependencies.\n\n```php\n<?php\n$binder->bindCallback(SomeInterface::class, function (SomeDependency $dependency) {\n    // Create an instance here.\n    return $instance;\n});\n```\n\n### Using with Injectable Factory\n\n*As of v7.0.*\n\nIt's possible to override default binding when creating instances with the injectable factory (usually this will be processed in your factory classes).\n\nThe binding will be applied to all dependencies of the class, including dependencies of dependencies and so on.\n\nExample:\n\n```php\n<?php\nuse Espo\\Core\\Binding\\BindingContainerBuilder;\nuse Espo\\Core\\Binding\\ContextualBinder;\n\n$bindingContainer = BindingContainerBuilder::create()\n    ->bindInstance(SomeInterface::class, $someInstance)\n    ->inContext(SomeClass::class, function (ContextualBinder $binder): void {\n        // Bind dependencies of `SomeClass`.\n        $binder->bindValue('$parameterName', 'some value');\n    })\n    ->build();\n    \n$instance = $injectableFactory->createWithBinding(SomeClass::class, $bindingContainer);\n```\n\nThe passed binding has a higher priority than the default binding (the default binding is applied globally to all objects resolved via DI).\n\n## See also\n\n* [Container services](container-services.md)\n"
  },
  {
    "path": "docs/development/duplicate-check.md",
    "content": "# Custom duplicate check\n\nDuplicate check is performed upon record creation. Optionally, it can be enabled for record update.\n\n*As of v7.0.*\n\nYou need to define a class name in metadata: recordDefs > {entityType} > duplicateWhereBuilderClassName. The class should implement `Espo\\Core\\Duplicate\\WhereBuilder` interface.\n\n### Example\n\nCreate `custom/Espo/Custom/Resources/metadata/recordDefs/Lead.json`:\n\n```json\n{\n    \"duplicateWhereBuilderClassName\": \"Espo\\\\Custom\\\\Classes\\\\DuplicateWhereBuilders\\\\Lead\"\n}\n```\n\nCreate a file `custom/Espo/Custom/Classes/DuplicateWhereBuilders/Lead.php`:\n\n```php\n<?php\nnamespace Espo\\Custom\\Classes\\DuplicateWhereBuilders;\n\nuse Espo\\Core\\Duplicate\\WhereBuilder;\n\nuse Espo\\ORM\\Query\\Part\\Condition as Cond;\nuse Espo\\ORM\\Query\\Part\\WhereItem;\nuse Espo\\ORM\\Query\\Part\\Where\\OrGroup;\nuse Espo\\ORM\\Entity;\n\nclass Lead implements WhereBuilder\n{\n    public function build(Entity $entity): ?WhereItem\n    {\n        $orBuilder = OrGroup::createBuilder();\n        \n        $toCheck = false;\n\n        if ($entity->get('firstName') || $entity->get('lastName')) {\n            $orBuilder->add(\n                Cond::and(\n                    Cond::equal(\n                        Cond::column('firstName'),\n                        $entity->get('firstName')\n                    ),\n                    Cond::equal(\n                        Cond::column('lastName'),\n                        $entity->get('lastName')\n                    )\n                )\n            );\n\n            $toCheck = true;\n        }\n        \n        // Here you can add more conditions.\n        \n        if (!$toCheck) {\n            return null;\n        }\n\n        return $orBuilder->build();\n    }\n}\n```\n\nYou can find built-in duplicate where-builders [here](https://github.com/espocrm/espocrm/tree/master/application/Espo/Classes/DuplicateWhereBuilders). You can reuse them for your entity.\n\n## Checking for duplicates when update\n\nDisabled by default. Can be enabled in metadata: recordDefs > {entityType} > updateDuplicateCheck.\n\n```json\n{\n    \"updateDuplicateCheck\": true\n}\n```\n"
  },
  {
    "path": "docs/development/dynamic-handler.md",
    "content": "# Dynamic Handler (complex dynamic forms)\n\nDynamic Handler provides the ability to manipulate the form (detail/edit views) appearance.\n\nNote that you can make forms dynamic with [Dynamic Logic](../administration/dynamic-logic.md) feature. Dynamic Handler is intended for more complex tasks where Dynamic Logic can be useless.\n\nAn example for the *Account* entity type.\n\nCreate a file `custom/Espo/Custom/Resources/metadata/clientDefs/Account.json`:\n\n```json\n{\n    \"dynamicHandler\": \"custom:account-dynamic-handler\"\n}\n```\n\nCreate a file `client/custom/src/account-dynamic-handler.js`:\n\n```js\n\ndefine('custom:account-dynamic-handler', ['dynamic-handler'], (Dep) => {\n\n    return class extends Dep {\n\n        // Called on initialization.\n        init() {\n            this.control();\n\n            // Invoke 'control' method every time assignedUserId gets changed.\n            this.recordView.listenTo(this.model, 'change:assignedUserId', () => this.control());\n            \n            // Changing another attribute on status change.\n            this.recordView.listenTo(this.model, 'change:status', (model, value, options) => {\n                if (!options.ui) {\n                    // Skip if the change was initiated not by a user interaction.\n                    // Important.\n                    return;\n                }\n                \n                if (value === 'Some Status') {\n                    setTimeout(() => this.model.set('someField', 'someValue'), 1);\n                }\n            });\n        }\n\n        control() {        \n            // if assigned user is not empty\n            if (this.model.get('assignedUserId')) {                \n                this.recordView.showField('sicCode');\n\n                this.recordView.setFieldRequired('type');\n                this.recordView.setFieldReadOnly('teams');\n\n                // set options\n                // actual for enum/array/multi-enum/checklist/varchar fields types\n                this.recordView.setFieldOptionList('type', ['Test', 'Hello']);\n\n                this.recordView.showPanel('activities');\n                \n                return;\n            }\n\n            this.recordView.hideField('sicCode');\n            this.recordView.setFieldNotRequired('type');\n            this.recordView.setFieldNotReadOnly('teams');\n            this.recordView.setFieldOptionList('type', ['Test']);\n            this.recordView.hidePanel('activities');\n        }\n    }\n});\n```\n\nThen, clear cache.\n\n!!! note\n\n    If you set model attributes from a model-change listener callback, you might need to use *setTimeout* with a zero or a small interval value. It will prevent some side effects.\n\n## Multiple dynamic handlers\n\nIt's possible to add multiple dynamic handlers to for one entity type. This allows different extensions to have their own dynamic handler.\n\nIn metadata > YourEntityType > clientDefs:\n\n```json\n{\n    \"dynamicHandlerList\": [\n        \"__APPEND__\",\n        \"custom:my-dynamic-handler\"\n    ]\n}\n```\n\n## Record view methods\n\nThe list of record view methods that may be useful in a dynamic handler.\n\n* hideField\n* showField\n* setFieldReadOnly\n* setFieldNotReadOnly\n* setFieldRequired\n* setFieldNotRequired\n* setFieldOptionList\n* resetFieldOptionList\n* showPanel\n* hidePanel\n* stylePanel\n* unstylePanel\n\n## See also\n\n* [Example for multi-enum fields](examples/dynamic-logic-multi-enum.md)\n"
  },
  {
    "path": "docs/development/email-sending.md",
    "content": "# Email Sending\n\nExample:\n\n```php\n<?php\nnamespace Espo\\SomeNamespace;\n\nuse Espo\\Core\\Mail\\EmailSender;\nuse Espo\\Core\\Mail\\EmailFactory;\nuse Espo\\Core\\Mail\\SmtpParams;\n\nclass SomeClass\n{   \n    public function __construct(\n        private EmailSender $emailSender,\n        private EmailFactory $emailFactory\n    ) {}\n    \n    public function send(): void\n    {\n        $email = $this->emailFactory->create();\n        \n        $email->setSubject('Subject');\n        $email->setBody('Email Body');\n        $email->addToAddress('some@address.com');\n        $email->setFromAddress('some@address.com'); // optional; if not specified, the system address will be used\n        $email->setIsPlain(); // Html is by default\n        \n        $smtpParams = SmtpParams::create(); // build SMTP params (optionally)\n\n        $this->emailSender\n            ->withSmtpParams($smtpParams) // optional\n            ->withAttachments([$attachment]) // optional, to send with attachments\n            ->send($email);\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/entry-points.md",
    "content": "# Entry Points\n\nEntry points offer distinct access routes to the application, each serving different functions apart from the REST API.\n\nEntry points are accessed by the following URL: `https://your-site-url?entryPoint={entryPointName}`. Note that *entryPointName* must start with a lower case letter.\n\nUsage examples:\n\n* file downloading;\n* rendering a web form that does not require authentication.\n\nEntry point classes are located in `Espo\\Module\\{ModuleName}\\EntryPoint` namespace.\n\n## Creating entry point\n\nAssuming that our module is named *ModuleName*.\n\nCreate a file `custom/Espo/Custom/Modules/ModuleName/EntryPoints/MyEntryPoint.php`:\n\n```php\n<?php\nnamespace Espo\\Modules\\ModuleName\\EntryPoints;\n\nuse Espo\\Core\\Api\\Request;\nuse Espo\\Core\\Api\\Response;\nuse Espo\\Core\\EntryPoint\\EntryPoint;\nuse Espo\\Core\\EntryPoint\\Traits\\NoAuth;\n\nclass MyEntryPoint implements EntryPoint\n{\n    // Allows access without authentication.\n    use NoAuth;\n\n    public function __construct(\n        // Pass needed dependencies.\n    ) {}\n\n    public function run(Request $request, Response $response): void\n    {\n        // Entry point logic.\n    }\n}\n```\n\nThen, clear cache.\n\nThe entry point will run on calling `https://your-site-url?entryPoint=myEntryPoint`.\n\n## Frontend rendering\n\nIt's possible to render the frontend and call a specific controller action from an entry point.\n\n```php\n<?php\nnamespace Espo\\Modules\\ModuleName\\EntryPoints;\n\nuse Espo\\Core\\Api\\Request;\nuse Espo\\Core\\Api\\Response;\nuse Espo\\Core\\EntryPoint\\EntryPoint;\nuse Espo\\Core\\EntryPoint\\Traits\\NoAuth;\nuse Espo\\Core\\Utils\\Client\\ActionRenderer;\n\nclass MyEntryPoint implements EntryPoint\n{\n    use NoAuth;\n\n    public function __construct(\n        private ActionRenderer $actionRenderer,\n    ) {}\n\n    public function run(Request $request, Response $response): void\n    {\n        $params = ActionRenderer\\Params\n            ::create('modules/my-module/controllers/my-controller', 'myAction')\n            ->withData(['key' => 'value']);\n\n        $this->actionRenderer->write($response, $params);\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/examples/dynamic-logic-multi-enum.md",
    "content": "# Example: Dynamic handler for multi-enum fields\n\nSee [the dynamic handler documentation](../dynamic-handler.md).\n\nIn this example we have two multi-enum fields `continents` and `countries`. We will make the logic that depending on selected continents only countries of those continents will be available for selection.\n\n1\\. Create (or open if exists) a file `custom/Espo/Custom/Resources/metadata/clientDefs/YourEntityType.json` (`YourEntityType` is the name of your entity type):\n\n```json\n{\n    \"dynamicHandler\": \"custom:my-dynamic-handler\"\n}\n```\n\n2\\. Create a file `client/custom/src/my-dynamic-handler.js`:\n\n```js\ndefine('custom:my-dynamic-handler', ['dynamic-handler'], (Dep) => {\n\n    return class extends Dep {\n\n        init() {\n            this.controlFields();\n            this.recordView.listenTo(this.model, 'change:continents', () => this.controlFields());\n        }\n\n        controlFields() {\n            const selectedContinentList = this.recordView.model.get('continents') || [];\n\n            const continentList = ['Africa', 'Asia', 'Europe', 'America'];\n\n            const countryMap = {\n                'Africa': ['Nigeria', 'Ethiopia'],\n                'Asia': ['India', 'Pakistan'],\n                'Europe': ['United Kingdom', 'France'],\n                'America': ['United States', 'Canada', 'Brazil'],\n            };\n\n            const countryList = [];\n\n            for (const continent of selectedContinentList) {\n                countryList = countryList.concat(\n                    countryMap[continent] || []\n                );\n            }\n\n            this.recordView.setFieldOptionList('countries', countryList);\n        }\n    }\n});\n```\n\n3\\. Clear cache at Administration > Clear Cache.\n\n4\\. You need to refresh a page in your browser.\n"
  },
  {
    "path": "docs/development/extension-packages.md",
    "content": "# Making extension package\n\n!!! note\n\n    It's recommended to use the [ext-template](https://github.com/espocrm/ext-template) repository for extension development.\n\nExtensions allow you to add extra functionality to EspoCRM. They can be installed at Administrator panel.\n\nThe file structure of the package:\n\n* `manifest.json` – a file that contains extension properties;\n* `files/` – a directory that contains extension files;\n* `scripts/` – a directory that contains extension scripts.\n\n## Manifest\n\n```json\n{\n  \"name\": \"Extension Name\",\n  \"version\": \"1.0.0\",\n  \"acceptableVersions\": [\n     \">=7.4.0\"\n  ],\n  \"php\": [\n     \">=8.1\"\n  ],\n  \"releaseDate\": \"2019-10-22\",\n  \"author\": \"Your name\",\n  \"description\": \"Description of your extension\"\n}\n```\n\nSyntax of `version` is described by the v2.0.0 the [SemVer](http://semver.org) specification. It's possible to define [ranges](https://getcomposer.org/doc/articles/versions.md#version-range) in `acceptableVersions`.\n\n## Files\n\nAll extension files should be placed in `files` directory. They will be copied to EspoCRM core directory.\n\n## Scripts\n\nFor different purposes EspoCRM supports the following types of scripts. All of them should be  placed in `scripts` directory.\n\n* `BeforeInstall.php` – a script executed before an installation process;\n* `AfterInstall.php` – executed once the installation process is finished;\n* `BeforeUninstall.php` – executed before uninstallation process;\n* `AfterUninstall.php` – executed once the uninstallation process is finished.\n\nExample:\n\n```php\n<?php\nuse Espo\\Core\\Container;\nuse Espo\\Core\\InjectableFactory;\nuse Espo\\Core\\Utils\\Config;\nuse Espo\\Core\\Utils\\Config\\ConfigWriter;\n\nclass AfterInstall\n{\n    public function run(Container $container): void\n    {\n        $config = $container->getByClass(Config::class);\n        \n        $configWriter = $container->getByClass(InjectableFactory::class)\n            ->create(ConfigWriter::class)\n \n        $tabList = $config->get('tabList') ?? [];\n       \n        if (!in_array('MyCustomEntity', $tabList)) {\n            $tabList[] = 'MyCustomEntity';\n           \n            $configWriter->set('tabList', $tabList);\n        }\n  \n        $configWriter->save();\n    }\n}\n```\n\n## Package\n\nIn the end, we need to pack all these files into a ZIP archive.\n\n## Template repository\n\nYou can use this [template repository](https://github.com/espocrm/ext-template) to create a git repository for your extension.\n\n## Recommendations\n\n!!! note\n\n    It's recommended to give some prefix to names of your custom entity types. E.g. `MyPrefixMyEntityTypeName`, this prefix can be the name of your company.\n    It will prevent possible conflicts with other extensions.\n"
  },
  {
    "path": "docs/development/frontend/ajax.md",
    "content": "# Ajax Requests\n\nThe *Espo.Ajax* object is used to make requests to Espo API endpoints. See the [source file](https://github.com/espocrm/espocrm/blob/master/client/src/ajax.js) with JSDoc for more info. An API base path `api/v1` is prepended to each request URL. \n\nGET:\n\n```js\nEspo.Ajax.getRequest(url, data, options)\n    .then(response => {})\n    .catch(xhr => {});\n```\n\nPOST:\n\n```js\nEspo.Ajax.postRequest(url, data, options)\n    .then(response => {})\n    .catch(xhr => {\n        if (xhr.status === 403) {\n            // Prevent error handling in the global handler.\n            xhr.errorIsHandled = true;\n            // Do something.\n        }\n    });\n```\n\nExample:\n\n```js\nEspo.Ajax.getRequest('MyController/action/getSomeDataById', {id: id})\n    .then(response => {\n        // A parsed response.\n        console.log(response);\n    });\n```\n\n## Request options\n\n* `[timeout] {Number}` A timeout in milliseconds.\n* `[headers] {Object.<string, string>}` A request headers.\n* `[dataType] {'xml'|'json'|'text'}` A data type.\n"
  },
  {
    "path": "docs/development/frontend/controller.md",
    "content": "# Client controller & routing\n\n## Routes\n\nClient routes are defined in metadata > app > clientRoutes.\n\nExample:\n\n```json\n{\n    \"MyEntityType/test/:id\": {\n        \"params\": {\n            \"controller\": \"custom:controllers/my-controller\",\n            \"action\": \"test\"\n        },\n        \"order\": 1\n    },\n    \"MyEntityType/hello/:id\": {\n        \"params\": {\n            \"controller\": \"MyEntityType\",\n            \"action\": \"hello\"\n        },\n        \"order\": 2\n    }\n}\n```\n\nIf a controller name starts with a capital letter, then the value is treated as a scope name – the class name will be determined by the *controller* parameter: metadata > clientDefs > {scope} > controller. \n\n## Custom route\n\nCreate a file `custom/Espo/Custom/Resources/metadata/app/clientRoutes.json`:\n\n```json\n{\n    \"Account/test/:id\": {\n        \"params\": {\n            \"controller\": \"custom:controllers/my-controller\",\n            \"action\": \"test\"\n        },\n        \"order\": 1\n    }\n}\n```\n\nCreate a client controller `client/custom/src/controllers/my-controller`:\n\n```js\ndefine(['controller'], (Controller) => {\n\n    return class extends Controller {\n\n        actionTest(options) {\n            console.log(options);\n        }\n    }\n});\n```\n\nClear cache.\n\nIf you open the URL `your-espo-url#Account/test/myId`  in the browser, it will execute the *actionTest* method. The *options* argument will be the object `{id: 'myId'}`.\n\n## Custom controller\n\nA scope controller.\n\nDefine a custom controller for the needed entity type (MyEntityType in our example).\n\nCreate a file `custom/Espo/Custom/Resources/metadata/clientDefs/MyEntityType.json`:\n\n```json\n{\n    \"controller\": \"custom:controllers/my-entity-type\"\n}\n```\n\nCreate a file `client/custom/src/controllers/my-entity-type.js`:\n\n```js\ndefine(['controllers/record'], (RecordController) => {\n\n    return class extends RecordController {\n\n        actionHello(options) {\n            console.log('action: hello');\n            console.log(options);\n        }\n\n        actionTest(options) {\n            if (!options.id) {\n                throw new Espo.Exceptions.NotFound();\n            }\n\n            console.log('action: test');\n            console.log(options);\n        }\n    }\n});\n```\n\nClear cache.\n\nIf you open in the browser URL `your-espo-url#MyEntityType/hello` it will execute *actionHello* method.\n\n`#MyEntityType/hello` – *options* variable value is an empty object\n`#MyEntityType/hello/p1=one&p2=two` – *options* variable value is an object `{p1: 'one', p2: 'two'}`\n\n## Rendering view\n\nIn controller:\n```js\n    actionTest(options) {\n        if (!options.id) {\n            throw new Espo.Exceptions.NotFound();\n        }\n\n        const id = options.id;\n\n        // we need to define the view in client/custom/src/views/account/test.js\n        const viewName = 'custom:views/account/test'; \n\n        // this will render view in the main container element #main\n        // id will be passed to the view\n        this.main(viewName, {id: id});\n    }\n```\n\nCreate a view `client/custom/src/views/account/test.js`:\n\n```js\ndefine('custom:views/account/test', ['view'], (View) => {\n\n    return class extends View {\n\n        // language=Handlebars\n        templateContent = `Id: {{id}}, name: {{name}}`\n\n        data() {\n            return {\n                id: this.model.id,\n                name: this.model.attributes.name,\n            }\n        }\n\n        setup() {\n            this.wait(this.loadModel());\n        }\n\n        async loadModel() {\n            this.model = await this.getModelFactory().create('Account');\n            this.model.id = this.options.id;\n\n            await this.model.fetch();\n        }\n    }\n});\n```\n"
  },
  {
    "path": "docs/development/frontend/dependency-injection.md",
    "content": "# Dependency injection in frontend\n\n*As of v9.0.*\n\n!!! note\n\n    Using dependency injection in the frontend requires transpiling step. Hence, you need to use the [ext-template](https://github.com/espocrm/ext-template) repository for customization development.\n\nIn this article:\n\n* [Injecting](#injecting)\n* [Registering](#registering)\n* [Built-in services](#built-in-services)\n\n## Injecting\n\nTo inject a service into a class, apply *@inject* decorator with a needed class to a class property. Note that the injected class must be registered as a service.\n\nExample:\n\n```js\nimport {inject} from 'di';\nimport Settings from 'models/settings';\n\nclass MyHelper {\n\n    /**\n     * @type {Settings}\n     */\n    @inject(Settings)\n    config\n}\n```\n\n## Registering\n\nTo register a service, apply *@register* decorator to a class.\n\nExample:\n\n```js\nimport {register} from 'di';\n\n@register()\nclass MyService {\n\n}\n```\n\n## Built-in services\n\n### storage\n\n`storage`\n\nA local browser storage. Stored values preserved when re-visiting the site from the same device.\n\n### session-storage\n\n`session-storage`\n\nA session browser storage. Stored values are not preserved when re-visiting the site.\n\n### settings\n\n`models/settings`\n\nConfig parameters.\n\n### preferences\n\n`models/preferences`\n\nUser preferences parameters.\n\n### user\n\n`models/user`\n\nA current user.\n\n### language\n\n`language`\n\nLabel translation functions.\n\n### metadata\n\n`metadata`\n\nApplication metadata.\n\n### app-params\n\n`app-params`\n\nApplication parameters.\n\n### model-factory\n\n`model-factory`\n\nCreates models for specific entity types.\n\n### collection-factory\n\n`collection-factory`\n\nCreates collections for specific entity types.\n\n### acl-manager\n\n`acl-manager`\n\nAccess control checking functions.\n\n### field-manager\n\n`field-manager`\n\nA util related to record fields.\n\n### date-time\n\n`date-time`\n\nA date-time util.\n\n### theme-manager\n\n`theme-manager`\n\nTheme related functions.\n\n### number-util\n\n`number-util`\n\nA number util. For working with numbers.\n\n### view-helper\n\n`view-helper`\n\nA view helper. Markdown, sanitizing, etc.\n\n### layout-manager\n\n`layout-manager`\n\nA record layout provider.\n\n### router\n\n`router`\n\nNavigation and routing functions. The confirm leave-out functionality.\n\n### web-socket-manager\n\n`web-socket-manager`\n\nWeb-socket functions.\n\n### broadcast-channel\n\n`broadcast-channel`\n\nFor communication between browser tabs.\n\n### page-title\n\n`page-title`\n\nA page title util.\n\n"
  },
  {
    "path": "docs/development/frontend/html-css.md",
    "content": "# HTML & CSS\n\n## Button\n\n```html\n<button class=\"btn {style-class}\">Label</button>\n```\n\nStyle classes:\n\n* `btn-default`\n* `btn-primary`\n* `btn-success`\n* `btn-danger`\n* `btn-warning`\n* `btn-info`\n* `btn-text`\n* `btn-link`\n\nWidth classes:\n\n* `btn-xs-wide`\n* `btn-s-wide`\n* `btn-wide`\n* `btn-xx-wide`\n* `btn-icon-wide`\n* `btn-icon-x-wide`\n* `btn-icon-xx-wide`\n* `btn-full-wide` – 100% width;\n\nSize classes:\n\n* `btn-sm`\n* `btn-lg`\n\nOther classes:\n\n* `btn-icon` – a button supposed to contain only an icon;\n\n### Button group\n\n```html\n<div class=\"btn-group\">\n    <button class=\"btn btn-default\"></button>\n    <button class=\"btn btn-default\"></button>\n</div>\n```\n\n## Dropdown\n\n```html\n<div class=\"btn-group\">\n    <button\n        class=\"btn btn-default dropdown-toggle\"\n        data-toggle=\"dropdown\"\n    >\n        <span class=\"fas fa-ellipsis-h\"></span>\n    </button>\n    <ul class=\"dropdown-menu pull-right\">\n        <li>\n            <a\n                role=\"button\"\n                tabindex=\"0\"\n                data-action=\"someAction\"\n            >Some Action</a>\n        </li>\n        <li class=\"divider\"></li>\n        <li>\n            <a\n                href=\"some-link\"\n                tabindex=\"0\"\n            >Some Link</a>\n        </li>\n    </ul>\n</div>\n```\n\nThe class `pull-right` is used to align the menu to the right side.\n\n## Panel\n\n```html\n<div class=\"panel panel-default\">\n    <div class=\"panel-heading\">\n        <h4 class=\"panel-title\">Title</h4>\n    </div>\n    <div class=\"panel-body\">\n    </div>\n</div>\n```\n\nStyle classes:\n\n* `panel-default`\n* `panel-success`\n* `panel-danger`\n* `panel-warning`\n* `panel-info`\n* `panel-primary`\n\n\nPanel body classes:\n\n* `panel-body-form` – for panels containing a form;\n\n## Table\n\n```html\n<table class=\"table\"></table>\n```\n\nClasses:\n\n* `table-fixed` – sets `table-layout: fixed`;\n* `table-no-overflow` – applies `overflow: hidden; text-overflow: ellipsis` to cells;\n* `table-striped`\n* `table-panel` – table like a panel;\n* `table-bordered-inside` – with cell borders;\n* `table-hover` – accent on row hover;\n* `no-margin` – no bottom margin;\n\nTH, TG tag classes:\n\n* `cell-nowrap` – suppresses line breaks;\n\nTR tag classes:\n\n* `accented`\n\n## List\n\n```html\n<ul class=\"list-group\">\n    <li class=\"list-group-item\"></li>\n</ul>\n```\n\n## Record\n\nA field cell on a form:\n\n```html\n<div class=\"cell form-group\" data-name=\"fieldName\">\n    <label class=\"control-label\" data-name=\"fieldName\">\n        <span class=\"label-text\">Label</span>\n    </label>\n    <div class=\"field\" data-name=\"fieldName\">\n        (field-element)\n    </div>\n</div>\n```\n\n## Grid\n\n### Columns\n\n12 columns system:\n\n```html\n<div class=\"row\">\n    <div class=\"col-sm-6\"></div>\n    <div class=\"col-sm-3\"></div>\n    <div class=\"col-sm-3\"></div>\n</div>\n```\n\n```html\n<div class=\"row\">\n    <div class=\"col-md-6 col-xs-12\"></div>\n    <div class=\"col-md-6 col-xs-12\"></div>\n</div>\n```\n\n```html\n<div class=\"row\">\n    <div class=\"col-md-6 col-md-offset-6\"></div>\n</div>\n```\n\nSupported screen widths:\n\n* `xs` – phones, 480px;\n* `sm` – tablets, 768px;\n* `md` – medium, 992px;\n* `lg` – large, 1200px;\n\n### Auto-fill grid\n\n```html\n<div class=\"grid-auto-fill-md\">\n    <div></div>\n    <div></div>\n    <div></div>\n</div>\n```\n\nSizes:\n\n* `xxs`\n* `xs`\n* `sm`\n* `md`\n\n## Type\n\n### Text\n\nStyle:\n\n* `text-soft`\n* `text-muted`\n* `text-primary`\n* `text-success`\n* `text-danger`\n* `text-warning`\n* `text-info`\n* `text-bold`\n* `text-italic` (as of v8.0)\n* `text-strikethrough` (as of v8.2)\n\nSize:\n\n* `text-large`\n* `text-2em`\n* `text-3em`\n* `text-4em`\n* `text-5em`\n* `text-6em`\n\n\n### Label\n\n```html\n<span class=\"label label-md label-default\">Text</span>\n```\n\nStyle classes:\n\n* `label-default`\n* `label-primary`\n* `label-success`\n* `label-danger`\n* `label-warning`\n* `label-info`\n\nSize classes:\n\n* `label-md`\n\n## Misc\n\nCentering:\n\n* `center-align` – applies `text-align: center`;\n\nA horizontally centered block:\n\n* `block-center`\n* `block-center-sm`\n* `block-center-md`\n\nA container that horizontally & vertically centers its child:\n\n* `container-centering`\n\nBorder radius:\n\n* `radius-left` – forces an element to have border radius on the left;\n* `radius-right` – forces an element to have border radius on the right;\n\nFloating:\n\n* `pull-left` – applies `float: left`;\n* `pull-right` – applies `float: right`;\n\nCancelling margins:\n\n* `no-margin` – cancels margins for an element contained in a panel and other containers;\n* `no-side-margin` – cancels side margins for an element contained in a panel and other containers;\n\nMargins:\n\n* `margin` – applies a margin to all sides;\n* `margin-top-sm`\n* `margin-top`\n* `margin-top-2x`\n* `margin-bottom-sm`\n* `margin-bottom`\n* `margin-bottom-2x`\n* `margin-bottom-3x`\n* `margin-bottom-4x`\n"
  },
  {
    "path": "docs/development/frontend/monkey-patching.md",
    "content": "# Monkey patching\n\n[Monkey patching](https://en.wikipedia.org/wiki/Monkey_patch) allows you to dynamically extend any frontend class.\n\n\n!!! warning\n\n    Monkey patching is not considered an upgrade-safe method and should be used as a last resort.\n\n1\\. Define the JS file that will be loaded with the Espo page.\n\nCreate `custom/Espo/Custom/Resources/metadata/app/client.json`:\n\n```json\n{\n    \"scriptList\": [\n        \"__APPEND__\",\n        \"client/custom/my-patch.js\"\n    ],\n    \"developerModeScriptList\": [\n        \"__APPEND__\",\n        \"client/custom/my-patch.js\"\n    ]\n}\n```\n\nNote that *developerModeScriptList* is only needed when you use the developer mode.\n\nAfter that, clear cache.\n\n2\\. Create a patching JS file.\n\nCreate `client/custom/my-patch.js`:\n\n```js\n/**\n *  In this example, we extend the login view.\n */\nrequire(['views/login'], View => {\n\n    const defaultAfterRender = View.prototype.afterRender;\n\n    // Extending the `afterRender` method.\n    View.prototype.afterRender = function () {\n        defaultAfterRender.call(this);\n\n        // Custom code here.\n        console.log(\"Custom login view is rendered.\");\n    };\n});\n```\n\nNote that you can patch multiple classes in one file.\n"
  },
  {
    "path": "docs/development/frontend/record-panels.md",
    "content": "# Custom panel on record (detail & edit) view\n\nAn example for *Account* entity type.\n\nCreate a file `custom/Espo/Custom/Resources/metadata/clientDefs/Account.json`:\n\n```json\n{\n    \"sidePanels\": {\n        \"detail\": [\n            \"__APPEND__\",\n            {\n                \"name\": \"myTestPanel\",\n                \"label\": \"My Test Panel\",\n                \"view\": \"custom:views/account/panels/my-test-panel\",\n                \"aclScope\": \"Account\",\n                \"acl\": \"edit\"\n            }\n        ]\n    }\n}\n```\n\nWe have defined a side panel for *detail* view. The following views are available:\n\n* detail\n* edit\n* detailSmall\n* editSmall\n\nYou can also define a bottom panel. Use *bottomPanels* key instead.\n\n\nThe values of parameters *aclScope* and *acl* mean, that the panel will be visible only if the user has *edit* access to *Account* entity type. You can omit both parameters.\n\nCreate a file `client/custom/src/views/account/panels/my-test-panel.js`:\n\n```js\ndefine(['views/record/panels/side'], (SidePanelView) => {\n\n    return class extends SidePanelView {\n\n        templateContent = '<div>{{viewObject.someKey}}</div>'\n\n        setup() {\n            this.someKey = 'Hello';\n        }\n    }\n});\n\n```\n\nNote, that if you define a bottom panel, you need to extend from `views/record/panels/bottom`.\n\nSee more [information](../view.md) about views.\n\n"
  },
  {
    "path": "docs/development/frontend/save-error-handlers.md",
    "content": "# Save error handlers\n\nWhen a record is being saved, it's possible to throw an exception in the backend and then handle it in the frontend.\n\nIn the backend the exception should be thrown with the *reason* parameter in the body. It can be done from a before-create or before-update [record hooks](../metadata/record-defs.md#beforereadhookclassnamelist).\n\nOnly `Conflict` and `Error` exceptions are supported.\n\n```php\n<?php\nuse Espo\\Core\\Exceptions\\ConflictSilent;\nuse Espo\\Core\\Utils\\Json;\n\nthrow ConflictSilent::createWithBody(\n    'myReason',\n    Json::encode([\n        'someKey1' => 'someValue1',\n        'someKey2' => 'someValue2',\n    ])\n);\n```\n\n!!! note\n\n    It's also possible to throw exceptions with formula in [API before-save script](../../administration/api-before-save-script.md).\n\nDefine a handler in metadata.\n\n`custom/Espo/Custom/Resources/metadata/clientDefs/{EntityType}.json`:\n\n```json\n{\n    \"saveErrorHandlers\": {\n        \"myReason\": \"custom:my-error-handler\"\n    }\n}\n```\n\nIt's also possible to define handlers for all entity types in `custom/Espo/Custom/Resources/metadata/clientDefs/Global.json`.\n\nCreate a handler `client/custom/src/my-error-handler.js`:\n\n```js\n\ndefine('custom:my-error-handler', [], function () {\n\n    return class {\n        constructor(view) {\n            /** @type {module:views/record/detail.Class} */\n            this.view = view;\n        }\n\n        process(data) {\n            Espo.Ui.error('Some error message.', true);\n            \n            // Some logic.\n        }\n    }\n});\n```\n"
  },
  {
    "path": "docs/development/frontend/templates.md",
    "content": "# Templates\n\nA template of a [view](../view.md) is used to render an HTML. Before rendering, the view passes data to the template. Templates can be stored in separate .tpl files or defined right in a the view's `templateContent` property. [Handlebars](https://handlebarsjs.com) library is used for templating.\n\n## Expressions\n\nExpressions are enclosed by double curly braces `{{}}`.\n\n```\n{{name}}\n```\n### Path\n\nWith dot-separated paths it's possible to look up in objects.\n\n```\n{{person.firstName}}\n```\n\n### Changing context\n\nInside `{{#each}}` blocks you can change a context to parent with `../`.\n\n```\n{{#each people}}\n    {{../prefix}} {{name}}\n{{/each}}\n```\n\n### HTML escaping\n\nValues returned by the `{{expression}}` are HTML-escaped. You can suppress escaping by using triple braces.\n\n```\n{{text}} – escaped\n{{{text}}} – unescaped\n```\n\nExpressions rendering child views should be unescaped.\n\n### Whitespaces\n\nTemplate whitespace can be omitted from either side of any mustache statement by adding a `~` character by the braces.\n\n```\n{{#each items ~}}\n    <button data-name=\"{{name}}\">{{label}}</button>\n{{~/each}}\n```\n\n### Sub-expressions\n\n```\n{{complexText (translate 'myMessage' category='messages' scope='MyScope')}\n```\n\n## Helpers\n\n### if\n\nAn if block conditional helper.\n\n```\n{{#if value}}\n\n{{/if}}\n```\n\n```\n{{#if value}}\n\n{{else}}\n\n{{/if}}\n```\n\n### unless\n\nAn inversion of the if block.\n\n### each\n\nAn iteration block helper.\n\n```\n{{#each array}}\n    {{this}} – item\n    {{@index}} – index\n{{/each}}\n```\n\n```\n{{#each object}}\n    {{this}} – item\n    {{@key}} – key\n{{/each}}\n```\n\n### lookup\n\nAccessing an object property by a key or an array item by an index.\n\n```\n{{lookup object 'property'}}\n```\n\n### ifEqual\n\nCompares two values for equality.\n\n```\n{{#ifEqual value1 value2}}\n\n{{/ifEqual}}\n```\n\n```\n{{#ifEqual value1 value2}}\n\n{{else}}\n\n{{/ifEqual}}\n```\n\n### ifNotEqual\n\nCompares two values for inequality.\n\n### get\n\nGets an attribute value from a model.\n\n```\n{{get model 'name'}}\n```\n\n### translate\n\nTranslates a label.\n\n```\n{{translate label}}\n{{translate field category='fields' scope='Account'}}\n```\n\n### translateOption\n\nTranslates an enum option.\n\n```\n{{translateOption 'optionKey' field='myField' scope='MyEntityType'}}\n```\n\n### complexText\n\nPrints a parsed Markdown text.\n\n```\n{{complexText text}}\n```\n\n### hyphen\n\nConverts a camelCase to hyphen.\n\n```\n{{hyphen stringValue}}\n```\n\n### toDom\n\nConvert a string from camelCase to hyphen and replace dots with hyphens. Useful for DOM attributes.\n\n```\ndata-{{toDom this}}=\"{{lookup ../this this}}\"\n```\n\n### breaklines\n\nReplaces line breaks with `<br>` tags.\n\n```\n{{breaklines text}}\n```\n\n### basePath\n\nA client base path.\n"
  },
  {
    "path": "docs/development/frontend/view-setup-handlers.md",
    "content": "# View Setup Handlers\n\n*As of v7.0*\n\nViewSetupHandlers framework provides the ability to customize existing views w/o extending. Multiple handlers can be attached to a view.\n\nIn clientDefs:\n\n```json\n{\n    \"viewSetupHandlers\": {\n        \"list\": [\n            \"__APPEND__\",\n            \"custom:some-handler-1\"\n        ],\n        \"record/search\": [\n            \"__APPEND__\",\n            \"custom:some-handler-2\"\n        ]\n    }\n}\n```\n\nCan be defined:\n\n* for a scope (clientDefs > {ScopeName})\n* globally (clientDefs > Global)\n\nHandlers are processed in the `setup` method of the view.\n\nThe following types are supported:\n\n* list – main list view;\n* detail – main detail view;\n* edit – main edit view;\n* record/list – list record view;\n* record/search – search view;\n* record/detail – detail record view;\n* record/edit – detail record view;\n* record/kanban – kanban record view;\n* login – the login view; only in Global scope; as of v8.3.0;\n\n!!! important\n\n    The `__APPEND__` element is needed in the beginning of arrays to establish extending of existing items that can be defined by other modules.\n\nHandler example:\n\n```js\n\ndefine('custom:some-handler', [], () => {\n\n    class Handler {\n        \n        /**\n         * @param {import('view').default} view\n         */\n        constructor(view) {\n            this.view = view;\n        }\n\n        process() {\n            this.listenTo(this.view, 'after:render', () => {\n                // Do something with view after render.\n            });\n\n            this.view.listenTo(this.view.model, 'change', () => {});\n        }\n    }\n\n    // Establish event support. If needed.\n    Object.assign(Handler.prototype, Backbone.Events);\n\n    return Handler;\n});\n```\n\nThe `process` method can return Promise. In this case the view will wait until the promise is resolved before proceeding to rendering.\n"
  },
  {
    "path": "docs/development/hooks.md",
    "content": "# Hooks\n\nThe Hooks framework provides the ability to catch some actions in the system in order to call custom logic.\n\nCommon hooks for all entity types (called from the ORM Repository class):\n\n- *beforeSave* – just before a record is saved;\n- *afterSave* – after a record is saved;\n- *beforeRemove* – before a record is removed;\n- *afterRemove* – after a record is removed;\n- *afterRelate* – when two records are related through a many-to-many relationship;\n- *afterUnrelate* – when two records are unrelated through a many-to-many relationship;\n- *afterMassRelate*\n- *lateAfterSave* – after a record is saved, after the transaction is committed (as of v10.0);\n- *lateAfterRemove* – after a record is removed, after the transaction is committed (as of v10.0);\n\n## Creating hook\n\n* create a file `custom/Espo/Custom/Hooks/{EntityType}/{HookName}.php` (you can also use a module directory);\n* declare a hook action method with a name the same as a hook name (e.g. *beforeSave*);\n* clear cache in Administration.\n\n!!! warning\n\n    {HookName} must be unique per entity type. If there are two hooks with the same name\n    for the same entity type (defined in different modules), only the first one will be applied (honoring the module order).\n\n## Hook order\n\nIf you have several hooks related to the same entity type, you can set the order property with an integer value.\n\n```\npublic static int $order = 10;\n```\n\nAscending order is applied – a hook with the smallest order number runs first.\n\nIf the *order* property is omitted, the value *9* is applied for the hook.\n\nOrder values of existing hooks:\n\n* Before-Save formula script: *11*\n* After-Save workflow actions: *99* (in Advanced Pack)\n\n### Interfaces\n\n*As of v7.4.*\n\nThere are interfaces for built-in hooks. It's recommended that your hooks implement these interfaces. This makes it easier for a developer to obtain needed data (passed to the hook) as each interface has a unique method signature. The list of interfaces:\n\n* `Espo\\Core\\Hook\\Hook\\BeforeSave`\n* `Espo\\Core\\Hook\\Hook\\AfterSave`\n* `Espo\\Core\\Hook\\Hook\\BeforeRemove`\n* `Espo\\Core\\Hook\\Hook\\AfterRemove`\n* `Espo\\Core\\Hook\\Hook\\AfterRelate`\n* `Espo\\Core\\Hook\\Hook\\AfterUnrelate`\n* `Espo\\Core\\Hook\\Hook\\AfterMassRelate`\n* `Espo\\Core\\Hook\\Hook\\LateAfterSave`\n* `Espo\\Core\\Hook\\Hook\\LateAfterRemove`\n\n## Example\n\nThis example sets an Account Name for new Leads, if it's not set.\n\n`custom/Espo/Custom/Hooks/Lead/MyHook.php`\n\n```php\n<?php\nnamespace Espo\\Custom\\Hooks\\Lead;\n\nuse Espo\\ORM\\Entity;\n\nclass MyHook\n{    \n    // An optional parameter, defines in which order hooks will be processed.\n    // Lesser value means sooner.\n    public static int $order = 5; \n    \n    public function __construct(\n        // Define needed dependencies.\n    ) {}\n\n    /**\n     * @param array<string, mixed> $options\n     */\n    public function beforeSave(Entity $entity, array $options): void\n    {\n        if ($entity->isNew() && !$entity->get('accountName')) { \n            $entity->set('accountName', 'No Account');\n        }\n    }\n}\n```\n\n## Global hooks\n\nIf you need to apply a hook for all entities, you can use common hooks. To do this, put your hook class to `Common` directory, for example, `custom/Espo/Custom/Hooks/Common/{HookName}.php`.\n\n## Additional default hooks\n\n#### TargetList\n\n* *afterOptOut* – when a target (recipient) clicks an opt-out link, data are passed in the 3rd $data argument;\n* *afterCancelOptOut* – when a target subscribes again;\n* *afterOptIn* – when a target opts-in through Lead Capture, data are passed in the 3rd $data argument;\n\n#### Meeting / Call\n\n* *afterConfirmation* – when an event attendee clicks on accept/decline/tentative link; details are passed in the 3rd argument $data;\n\n#### Contact\n\n* *afterLeadCapture* – when a contact (existing in crm) opts-in through Lead Capture, leadCaptureId is passed in the 3rd argument $data;\n* *afterOptOut*\n* *afterCancelOptOut*\n\n#### Lead\n\n* *afterLeadCapture* – when a lead opts-in through Lead Capture, leadCaptureId is passed in the 3rd argument $data;\n* *afterOptOut*\n* *afterCancelOptOut*\n\n#### LeadCapture\n\n* *afterLeadCapture* – when a target (lead or contact) opts-in through Lead Capture, target data are passed in the 3rd argument $data;\n\n#### CampaignTrackingUrl\n\n* *afterClick* - when a target (lead/contact/account) opened a tracking url in email;\n\n#### Examples\n\n`custom/Espo/Custom/Hooks/TargetList/MyHook.php`\n\n```php\n<?php\nnamespace Espo\\Custom\\Hooks\\TargetList;\n\nuse Espo\\ORM\\Entity;\n\nclass MyHook\n{    \n    public function afterOptOut(Entity $targetList, array $options, array $data): void\n    {\n        $targetId = $data['targetId'];\n        $targetType = $data['targetType'];\n        $link = $data['link'];\n    }\n}\n```\n\n`custom/Espo/Custom/Hooks/Meeting/MyHook.php`\n\n```php\n<?php\nnamespace Espo\\Custom\\Hooks\\Meeting;\n\nuse Espo\\ORM\\Entity;\n\nclass MyHook\n{    \n    public function afterConfirmation(Entity $meeting, array $options, array $data): void\n    {\n        $status = $data['status'];\n        $inviteeType = $data['inviteeType'];\n        $inviteeId = $data['inviteeId'];\n        \n        if ($status === 'Accepted') {\n        \n        }\n    }\n}\n```\n\n### Triggering hook\n\nInject the hook manager `Espo\\Core\\HookManager` to your class. Use the `process` method.\n\n```php\n<?php\n$this->hookManager->process($entityType, $hookType, $entity, $options);\n```\n\n!!! note\n\n    A hook name can't start with `set`. It's reserved for a dependency injection.\n\n## Tips\n\nAvoid saving the same record in beforeSave hooks.\n\nIn afterSave hooks, re-saving the same record usually should be avoided as it can disrupt following hooks. If saving is needed, consider passing SKIP_ALL, KEEP_NEW and KEEP_DIRTY save options to the *saveEntity* method or run an update query instead (using the query builder).\n"
  },
  {
    "path": "docs/development/how-to-create-a-dashlet.md",
    "content": "# Custom dashlets\n\nCreate a file `custom/Espo/Custom/Resources/metadata/dashlets/{DASHLET_NAME}.json` with your dashlet configuration.\n\nHere you need to define `\"view\"`, and you can set 'aclScope', and 'options'.\n\nIf it's typical list dashlet, use `\"view\":\"views/dashlets/abstract/record-list\"`, if not, create own [view](custom-views.md).\n\n## Options\n\nBy default in dashlet options you can set _Title_ and _Auto-refresh Interval_.\n\nAdditional option fields you can set in `\"options\"` > `\"fields\"`.\n\nAlso you can define other options, if your view needs more data. You will be able to access options data from a view with the method `getOption('optionName')`.\n\n## Example\n\nCreate a file `custom/Espo/Custom/Resources/metadata/dashlets/MyDashlet.json`:\n\n```json\n{\n    \"view\": \"custom:views/dashlets/my-dashlet\",\n    \"aclScope\": \"Account\",\n    \"options\": {\n        \"fields\": {\n            \"title\": {\n                \"type\": \"varchar\",\n                \"required\": true\n            },\n            \"autorefreshInterval\": {\n                \"type\": \"enumFloat\",\n                \"options\": [0, 0.5, 1, 2, 5, 10]\n            }\n        },\n        \"layout\": [\n            {\n                \"rows\": [\n                    [\n                        {\"name\": \"title\"},\n                        {\"name\": \"autorefreshInterval\"}\n                    ]\n                ]\n            }\n        ]\n    }\n}\n```\naclScope set to Account means that only users who have access to Account scope will be able to add this dashlet.\n\n\nThere you can find how default dashlets defined: `application/Espo/Modules/Crm/Resources/metadata/dashlets`.\n\nCreate a view file `client/custom/src/views/dashlets/my-dashlet.js`:\n\n```js\ndefine(['views/dashlets/abstract/base'], (BaseView) => {\n\n    return class extends BaseView {\n        name = 'MyDashlet'\n\n        templateContent = `\n            <p>My Dashlet</p>\n            <iframe src=\"\"></iframe>\n        `\n    }\n});\n```\n\n## Translation\n\nTranslation to dashlet is in `Global` scope, in `\"dashlets\"` section.\n\n__After that don't forget to Clear Cache in Administration.__\n"
  },
  {
    "path": "docs/development/how-to-start.md",
    "content": "# How to get started\n\n*(for developers)*\n\nIn this article:\n\n* [Option A. Extension development](#option-a-extension-development)\n* [Option B. Using git repository](#option-b-using-git-repository)\n* [Configuration for development](#configuration-for-development)\n* [Where to put customizations](#where-to-put-customizations)\n\n## Option A. Extension development\n\nUse this approach to customize Espo for a specific business. \n\nBy utilizing the [ext-template](https://github.com/espocrm/ext-template) repository, you can craft an installable extension for EspoCRM. Your repository will contain only your custom files. The ext-template tools allow you to run your extension in an Espo instance for testing purposes. See more info in the repository's readme.\n\nIt is possible to [install](autoload.md) additional composer libraries in your extension.\n\n## Option B. Using git repository\n\nUsing the main EspoCRM repository. Contributors should use this approach.\n\n1. Clone [https://github.com/espocrm/espocrm](https://github.com/espocrm/espocrm) repository (or a forked one) to your local computer.\n2. Change to the project's root directory: `cd path/to/espocrm`.\n3. Install [Composer](https://getcomposer.org/doc/00-intro.md) if not installed (v2.0 or greater).\n4. Install npm if not installed (v8.0 or greater).\n5. Install [Grunt](https://gruntjs.com/installing-grunt).\n6. Run `composer install` if Composer is installed globally (or, `php composer.phar install`, if locally).\n7. Run `npm ci`.\n\nThen, you can build by running `grunt`.\n\nTo build a proper *config.php* file and populate database you can run installation. Open `http(s)://{YOUR_CRM_URL}/install` location in the browser. It's assumed that your webserver is properly [configured](../administration/server-configuration.md).\n\n!!! note\n\n    Some dependencies require php extensions that you might not have installed. You can skip these requirements by installing with a flag *--ignore-platform-reqs*: `composer install --ignore-platform-reqs`.\n\nYou also need to enable [developer mode](#configuration-for-development).\n\nAfter building, you will be able to run the instance in your browser right from the project root directory, considering that your web server is properly configured.\n\n### Building\n\n1. Change to the project's root directory.\n2. Run Grunt with `grunt`.\n\nThe build will be created in the `build` directory.\n\n!!! note\n\n    By default, grunt installs composer dependencies. You can skip it by running `grunt offline`.\n\n\n#### Javascript transpiling\n\nBuilding with *grunt* includes the transpiling step. You can also run it manually with the following commands.\n\nTranspile all:\n\n```\nnode js/transpile\n```\n\nTranspile a specific file (can be useful for a file watcher in an IDE):\n\n```\nnode js/transpile -f $FilePathRelativeToProjectRoot$\n```\n\n### Branches\n\n* *fix* – upcoming maintenance release; fixes should be pushed to this branch;\n* *master* – develop branch; new features should be pushed to this branch;\n* *stable* – last stable release.\n\n### Upgrade packages\n\nPreparation:\n\n1. Fetch tags to your git repository from the remote: `git fetch --tags`.\n2. Checkout to a needed version tag (or don't if you want to test upgrade to the most recent commit).\n3. Build EspoCRM with grunt (see above how to build).\n\nBuild the upgrade package with the command:\n\n```\nnode diff {version_from}\n```\n\nThe package will be created in the `build` directory.\n\n### Using custom builds for production\n\nOne may want to maintain a forked and customized repository to use it for production. Note that this is not an officially supported approach but it's still viable.\n\nPrinciples:\n\n1. Merge with upstream.\n2. Build upgrades by yourself.\n3. Production instance should be installed from a build (artifact). It should not be the same as the development repository.\n4. Do not apply upgrades against the development repository, upgrade the production instance.\n\n## Configuration for development\n\nEspoCRM instance configuration for development. Config parameters should be set in `data/config.php`.\n\nThe developer mode:\n\n```php\n'isDeveloperMode' => true,\n```\n\n!!! note\n\n    The developer mode won't work on a release instance. It requires the *frontend* folder from the repository and *client/lib/transpiled* which should contain all JS files separately and transpiled.\n\nYou can force using some additional cache in the developer mode. Can be reasonable as the application can run very slow w/o cache.\n\n```php\n'useCacheInDeveloperMode' => true,\n```\n\n## Where to put customizations\n\n### Option A. Custom dirs\n\n* `custom/Espo/Custom/` – for metadata and all files pertaining to backend\n* `client/custom/` – for client files\n\n### Option B. Module dirs\n\n* `custom/Espo/Modules/{YourModuleName}/` – for metadata and all files pertaining to backend\n* `client/custom/modules/{your-module-name}/` – for client files\n\nThis method is the only appropriate method when developing an extension. The ext-template's initialization created needed folders automatically. The important advantage of using ext-template is the ability to use ESM modules in the frontend, which significantly improves the development experience.\n"
  },
  {
    "path": "docs/development/index.md",
    "content": "# Developer Documentation\n\n### General\n\n* [Getting started](how-to-start.md)\n* [Making extension package](extension-packages.md)\n* [Modules](modules.md)\n* [Tests](tests.md)\n* [Translation](translation.md)\n* [Coding rules](coding-rules.md)\n\n### Backend\n\n* [Dependency injection](di.md)\n* [Metadata](metadata.md)\n* [ORM](orm.md)\n* [Select Builder](select-builder.md)\n* [API actions](api-action.md)\n* [Services](services.md)\n* [Hooks](hooks.md)\n* [ACL](acl.md)\n* [Entry points](entry-points.md)\n* Misc\n  * [Coding practices'](coding-practices.md) \n  * [Autoload](autoload.md)\n  * [Entity type](custom-entity-type.md)\n  * [Container services](container-services.md)\n  * [Template helpers (PDF)](template-custom-helper.md)\n  * [Formula functions](new-function-in-formula.md)\n  * [Scheduled jobs](scheduled-job.md)\n  * [Duplicate checking](duplicate-check.md)\n  * [Database indexes](db-indexes.md)\n  * [App params](app-params.md)\n  * [Jobs](jobs.md)\n  * [Email sending](email-sending.md)\n  * [Calculated fields](calculated-fields.md)\n  * [Config parameters](custom-config-parameters.md)\n  * [Attachments](attachments.md)\n\n### Frontend\n\n* [View](view.md)\n* [Model](model.md)\n* [Collection](collection.md)\n* [Templates](frontend/templates.md)\n* [HTML & CSS](frontend/html-css.md)\n* [Ajax requests](frontend/ajax.md)\n* [Controller & routing](frontend/controller.md)\n* [Dependency injection](frontend/dependency-injection.md)\n* [Modal dialogs](modal.md)\n* [Confirmation dialogs](confirm-dialog.md)\n* [Custom views (for records and fields)](custom-views.md)\n* [View setup handlers](frontend/view-setup-handlers.md)\n* [Save error handlers](frontend/save-error-handlers.md)\n* [Dynamic forms with dynamic handler](dynamic-handler.md)\n* Fields\n  * [Custom field type](custom-field-type.md)\n  * [Customizing existing fields](customize-standard-fields.md)\n* Misc\n  * [Buttons & dropdown actions for detail/edit/list views](custom-buttons.md)\n  * [Custom panels on record view](frontend/record-panels.md)\n  * [Including custom CSS file](custom-css.md)\n  * [Custom dashlets](how-to-create-a-dashlet.md)  \n  * [Link-multiple field with primary record](link-multiple-with-primary.md)\n  * [Monkey patching](frontend/monkey-patching.md)\n  * Campaigns\n    * [Custom unsubscribe page](campaign-unsubscribe-template.md)\n\n\n### API\n\n* [API Overview](api.md)\n"
  },
  {
    "path": "docs/development/jobs.md",
    "content": "# Jobs\n\nSometimes it's reasonable to execute some actions in background. For example, when sending an email, to prevent a user to wait until sending is processed. \n\n### Scheduling\n\n```php\n<?php\nuse Espo\\Core\\Job\\JobSchedulerFactory;\nuse Espo\\Core\\Job\\QueueName;\n\n/** @var JobSchedulerFactory $jobSchedulerFactory */\n$jobSchedulerFactory->create()\n    ->setClassName($jobClassName) // should implement `Espo\\Core\\Job\\Job` interface\n    ->setQueue(QueueName::Q0) // optional\n    ->setGroup('some-group-name') // optional\n    ->setData([\n        'someKey' => $someValue,\n    ])\n    ->schedule();\n```\n\nYou can pass JobSchedulerFactory as a constructor dependency.\n\n### Job\n\n```php\n<?php\nnamespace Espo\\Custom\\MyJobs;\n\nuse Espo\\Core\\Job\\Job;\nuse Espo\\Core\\Job\\Job\\Data;\n\nclass MyJob implements Job\n{\n     public function __construct(/* pass needed dependencies */)\n     {}\n     \n     public function run(Data $data): void\n     {\n         // job logic here\n     }\n}\n```\n\n### Queues\n\nJobs within a queue are processed one by one.\n\nQueues available out of the box:\n\n* e0 – intended for email sending; run as often as possible; one-by-one;\n* q0 – for general use; run as often as possible; one-by-one;\n* q1 – for general use; run every minute; one-by-one;\n* m0 – run in-parallel along with the main queue; used to avoid disruption of the main queue; as of v9.2.\n\nPortion size is controller by [config parameters](../administration/config-params.md#jobs-daemon).\n\n### Groups\n\nA group name can be any string with max length of 128 characters. Jobs with the same group name are processed one by one.\n"
  },
  {
    "path": "docs/development/link-multiple-with-primary.md",
    "content": "# Link Multiple field with Primary\n\nSometimes you have a *hasMany* relationship and need to have the ability to a select primary record among related ones. As example, a *Contacts* field of the *Case* entity.\n\n>Need to create a `contacts` linkMultiple field with a primary for our custom entity *Stock*. \n>\n\n### Step 1\n\nCreate (or edit) `custom/Espo/Custom/Resources/metadata/entityDefs/Stock.json`:\n\n```json\n{\n    \"fields\": {\n        \"contacts\": {\n            \"type\": \"linkMultiple\",\n            \"view\": \"custom:views/stock/fields/contacts\"\n        },\n        \"contact\": {\n            \"type\": \"link\"\n        }\n    },\n    \"links\":{\n        \"contact\": {\n            \"type\": \"belongsTo\",\n            \"entity\": \"Contact\",\n            \"foreign\": \"stocksPrimary\"\n        },\n        \"contacts\": {\n            \"type\": \"hasMany\",\n            \"entity\": \"Contact\",\n            \"foreign\": \"stocks\",\n            \"layoutRelationshipsDisabled\": true\n        }\n    }\n}\n```\n\n### Step 2\n\n`custom/Espo/Custom/Resources/metadata/entityDefs/Contact.json`\n\n```json\n{\n    \"links\":{\n        \"stocksPrimary\": {\n            \"type\": \"hasMany\",\n            \"entity\": \"Stock\",\n            \"foreign\": \"contact\",\n            \"layoutRelationshipsDisabled\": true\n        },\n        \"stocks\": {\n            \"type\": \"hasMany\",\n            \"entity\": \"Stock\",\n            \"foreign\": \"contacts\"\n        }\n    }\n}\n```\n\n### Step 3\n`custom/Espo/Custom/Hooks/Stock/AfterSave.php`\n\n```php\n<?php\nnamespace Espo\\Custom\\Hooks\\Stock;\n\nuse Espo/ORM/Entity;\nuse Espo/ORM/EntityManager;\n\nclass AfterSave\n{\n    public function __construct(private EntityManager $entityManager) {}\n\n    public function afterSave(Entity $entity, array $options): void\n    {            \n        if (!$entity->isAttributeChanged('contactId')) {\n            return;\n        }\n        \n        $contactId = $entity->get('contactId');\n        $fetchedContactId = $entity->getFetched('contactId');\n        \n        $relation = $this->entityManager\n            ->getRDBRepository($entity->getEntityType())\n            ->getRelation($entity, 'contacts');\n\n        if (!$contactId) {\n            $relation->unrelateById($fetchedContactId);\n            \n            return;\n        }\n        \n        $relation->relateById($contactId);        \n    }\n}\n```\n\n### Step 4\n`client/custom/src/views/stock/fields/contacts.js`\n\n```js\ndefine(['views/fields/link-multiple-with-primary'], (Dep) => {   \n    return class extends Dep {\n        primaryLink = 'contact'\n    }\n});\n```\n\n### Step 5\n\nRun Rebuild.\n\n### Step 6\n\nExecute an SQL query:\n\n```sql\nUPDATE stock\nJOIN contact_stock\nON contact_stock.stock_id = stock.id AND contact_stock.deleted = 0\nSET stock.contact_id = contact_stock.contact_id\n```\n"
  },
  {
    "path": "docs/development/metadata/acl-defs.md",
    "content": "# aclDefs\n\nPath: metadata > aclDefs > {ScopeName}.\n\nDefines access control parameters for a specific scope (or entity type).\n\n## accessCheckerClassName\n\nAn access checking class. Should implement `Espo\\Core\\Acl\\AccessChecker` interface.\n\nCan optionally implement more interfaces that define what actions can be checked.\n\nInterfaces for access checking:\n\n* `Espo\\Core\\Acl\\AccessChecker` – access to a scope;\n* `Espo\\Core\\Acl\\AccessCreateChecker` – access to a create operation for a scope;\n* `Espo\\Core\\Acl\\AccessReadChecker` – access to a read operation for a scope;\n* `Espo\\Core\\Acl\\AccessEditChecker` – access to an edit operation for a scope;\n* `Espo\\Core\\Acl\\AccessDeleteChecker` – access to a delete operation for a scope;\n* `Espo\\Core\\Acl\\AccessStreamChecker` – access to the stream for a scope;\n* `Espo\\Core\\Acl\\AccessEntityCreateChecker` – access to a create operation for an entity;\n* `Espo\\Core\\Acl\\AccessEntityReadChecker` – access to a read operation for an entity;\n* `Espo\\Core\\Acl\\AccessEntityEditChecker` – access to an edit operation for an entity;\n* `Espo\\Core\\Acl\\AccessEntityDeleteChecker` – access to a delete operation for an entity;\n* `Espo\\Core\\Acl\\AccessEntityStreamChecker` – access to the stream of an entity.\n\nCombined interfaces:\n\n* `Espo\\Core\\Acl\\AccessEntityCREDChecker` – access to create/read/edit/delete of an entity (combined);\n* `Espo\\Core\\Acl\\AccessEntityCREDSChecker` – access to create/read/edit/delete/stream of an entity (combined).\n\n\nDefault class: `Espo\\Core\\Acl\\DefaultAccessChecker`.\n\n\n## ownershipCheckerClassName\n\nAn ownership checking class.\n\nShould implement one of the following interfaces:\n\n* `Espo\\Core\\Acl\\OwnershipOwnChecker`  – whether a user is an owner of an entity;\n* `Espo\\Core\\Acl\\OwnershipTeamChecker` – whether an entity belongs to a user team.\n\nDefault class: `Espo\\Core\\Acl\\DefaultOwnershipChecker`.\n\n## portalAccessCheckerClassName\n\nThe same as `accessCheckerClassName` but for the portal.\n\n## portalOwnershipCheckerClassName\n\nThe same as `ownershipCheckerClassName` but for the portal.\n\nCan implement additional interfaces:\n\n* `Espo\\Core\\Portal\\Acl\\OwnershipAccountChecker`\n* `Espo\\Core\\Portal\\Acl\\OwnershipContactChecker`\n\n## assignmentCheckerClassName\n\nAn assignment checking class.\n\nShould implement `Espo\\Core\\Acl\\AssignmentChecker` interface.\n\nDefault class: `Espo\\Core\\Acl\\DefaultAssignmentChecker`.\n\n## readOwnerUserField\n\nIndicates what field is used for ownership checking. If an entity uses a field other than *assignedUser* or *assignedUsers*, you need to specify that field.\n\n## linkCheckerClassNameMap \n\n*Object.<string, class-string<Espo\\Core\\Acl\\LinkChecker\\>\\>*\n\n*As of v7.4.*\n\nLinking/unlinking checking classes for specific links. A link-name => class-string map. The class receives two entities and should determine whether a user is allowed to link/unlink these records.\n\n\n## accountLink\n\n*As of v9.0.*\n\nA link with Account that will be used when access control applied for portal users.\n\n## contactLink\n\n*As of v9.0.*\n\nA link with Contact that will be used when access control applied for portal users.\n"
  },
  {
    "path": "docs/development/metadata/app-acl-portal.md",
    "content": "# app > aclPortal\n\nPath: metadata > app > aclPortal.\n\nAccess control level parameters for portals. Has the same parameters as [app > acl](app-acl.md).\n"
  },
  {
    "path": "docs/development/metadata/app-acl.md",
    "content": "# app > acl\n\nPath: metadata > app > acl.\n\nAccess control level parameters for the system (excluding portals).\n\n## mandatory\n\n*Object.<string, Object\\>*\n\nAccess levels forcibly applied for regular and API users. These roles can't be changed by Roles assigned to a user.\n\n### scopeLevel\n\n*Object.<string, (Object|boolean|string)\\>*\n\nMandatory access levels for specific scopes.\n\nExample:\n\n```json\n{\n    \"mandatory\": {\n        \"scopeLevel\": {\n            \"MyEntityType1\": {\n                \"create\": \"yes\",\n                \"read\": \"own\",\n                \"edit\": \"own\",\n                \"delete\": \"own\",\n                \"stream\": \"team\"\n            },\n            \"MyScope1\": true,\n            \"WorkingTimeRange\": \"WorkingTimeCalendar\"\n        }\n    }\n}\n```\n\n* If set to *false*, then users won't have access to the scope.\n* True enables access to scopes w/o actions (scopes that have `\"acl\": \"boolean\"` in metadata > scopes).\n* A string value makes the framework to use roles from another scope and apply it to our scope. It can be useful to have roles only for one parent scope, when child scopes uses roles of the parent scope. E.g. *WorkingTimeCalendar* is a parent, *WorkingTimeRange* is a child. In Roles the admin defines only access levels to *WorkingTimeCalendar*, *WorkingTimeRange* will have the same access levels.\n* A string value in the format `boolean:{scope}` will convert a foreign scope data to a boolean value. As of v8.4.\n\n### scopeFieldLevel\n\n*Object.<string, Object.<string, Object|false\\>\\>*\n\nMandatory access levels for fields for scopific scopes (entity types). Available levels: *yes*, *no*. False disables access to a field.\n\nExample:\n\n```json\n{\n    \"mandatory\": {\n        \"scopeFieldLevel\": {\n            \"MyEntityType\": {\n                \"myField1\": {\n                    \"read\": \"yes\",\n                    \"edit\": \"no\"\n                },\n                \"myField2\": false\n            }\n        }\n    }\n}\n```\n\n### fieldLevel\n\n*Object.<string, (Object|false)\\>*\n\nMandatory access levels for fields for any scope (entity type). E.g. if we define access levels to a field *assignedUsers*, then all fields with the name *assignedUsers* will obtain defined access levels (regardless of an entity type).\n\n\nExample:\n\n```json\n{\n    \"mandatory\": {\n        \"fieldLevel\": {\n            \"myField1\": {\n                \"read\": \"yes\",\n                \"edit\": \"no\"\n            },\n            \"myField2\": false\n        }\n    }\n}\n```\n\n## adminMandatory\n\n*Object.<string, Object\\>*\n\nAccess levels forcibly applied for admin users. This section has the same parameters as the *mandatory* section: scopeLevel, scopeFieldLevel, fieldLevel.\n\n## strictDefault\n\n*Object.<string, Object\\>*\n\nAccess levels applied for regular and API users when access is not defined by Roles assigned to those users. This section has the same parameters as the *mandatory* section: scopeLevel, scopeFieldLevel, fieldLevel.\n\n## valuePermissionList\n\n*string[]*\n\nThe list of all available [permissions](../../administration/roles-management.md#special-permissions) in the system.\n\nExample:\n\n```json\n{\n    \"valuePermissionList\": [\n        \"assignmentPermission\",\n        \"userPermission\",\n        \"portalPermission\",\n        \"groupEmailAccountPermission\",\n        \"exportPermission\",\n        \"massUpdatePermission\",\n        \"followerManagementPermission\",\n        \"dataPrivacyPermission\"\n    ]\n}\n```\n\nUse `__APPEND__` as the first value if you want to extend the list.\n\n## permissionsStrictDefaults\n\n*Object.<string, \"all\"|\"yes\"|\"team\"|\"own\"\\>*\n\nPermissions applied for regular and API users when they are not defined by Roles assigned to those users.\n\nExample:\n\n```json\n{\n    \"permissionsStrictDefaults\": {\n        \"assignmentPermission\": \"no\",\n        \"userPermission\": \"no\",\n        \"portalPermission\": \"no\",\n        \"groupEmailAccountPermission\": \"no\",\n        \"exportPermission\": \"no\",\n        \"massUpdatePermission\": \"no\",\n        \"followerManagementPermission\": \"no\",\n        \"dataPrivacyPermission\": \"no\"\n    }\n}\n```\n\n## valuePermissionHighestLevels\n\n*Object.<string, \"all\"|\"yes\"|\"team\"|\"own\"\\>*\n\nHighest levels for permissions.\n\nExample:\n\n```json\n{\n    \"valuePermissionHighestLevels\": {\n        \"assignmentPermission\": \"all\",\n        \"userPermission\": \"all\",\n        \"portalPermission\": \"yes\",\n        \"groupEmailAccountPermission\": \"all\",\n        \"exportPermission\": \"yes\",\n        \"massUpdatePermission\": \"yes\",\n        \"followerManagementPermission\": \"all\",\n        \"dataPrivacyPermission\": \"yes\"\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-actions.md",
    "content": "# app > actions\n\nPath: metadata > app > actions.\n\nDefinitions for the [Action]() framework. An action-name => Object map. A called action is applied to a single record.\n\nExample:\n\n```json\n{\n    \"convertCurrency\": {\n        \"implementationClassName\": \"Espo\\\\Core\\\\Action\\\\Actions\\\\ConvertCurrency\"\n    },\n    \"merge\": {\n        \"implementationClassName\": \"Espo\\\\Core\\\\Action\\\\Actions\\\\Merge\"\n    }\n}\n```\n\nAPI endpoint: `POST Action`.\n\nAPI payload params:\n\n* entityType – *string*\n* action – *string*\n* id – *string*\n* data – *Object.<string, mixed\\>*\n\n## implementationClassName\n\nAn action class. Should implement `Espo\\Core\\Action\\Action` interface. Can be overridden for a specific entity type at: recordDefs > {EntityType} > actions > {action} > implementationClassName.\n"
  },
  {
    "path": "docs/development/metadata/app-address-formats.md",
    "content": "# app > addressFormats\n\nA mapping format => params. Defines address formats (used in the backend).\n\n## formatterClassName\n\n*class-string<Espo\\Core\\Field\\Address\\AddressFormatter\\>*\n\nA formatter class. Should implement `Espo\\Core\\Field\\Address\\AddressFormatter` interface.\n\nExample:\n\n```json\n{\n    \"1\": {\n        \"formatterClassName\": \"Espo\\\\Classes\\\\AddressFormatters\\\\Formatter1\"\n    },\n    \"2\": {\n        \"formatterClassName\": \"Espo\\\\Classes\\\\AddressFormatters\\\\Formatter2\"\n    },\n    \"3\": {\n        \"formatterClassName\": \"Espo\\\\Classes\\\\AddressFormatters\\\\Formatter3\"\n    },\n    \"4\": {\n        \"formatterClassName\": \"Espo\\\\Classes\\\\AddressFormatters\\\\Formatter4\"\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-admin-panel.md",
    "content": "# app > adminPanel\n\nPath: metadata > app > adminPanel.\n\nDefines what to display on the Administration page.\n\n```json\n{\n    \"panelName\": {\n        \"label\": \"Some Panel Label\",\n        \"itemList\": [\n            {\n                \"url\": \"#SomeUrl\",\n                \"label\": \"Some Item Label\",\n                \"iconClass\": \"fas fa-cogs\",\n                \"description\":\"descriptionLanguageKey\",\n                \"tabQuickSearch\": true\n            },\n            {\n                \"url\": \"#Admin/mySettingsPage\",\n                \"label\": \"My Settings\",\n                \"iconClass\": \"fas fa-cogs\",\n                \"description\":\"mySettings\",\n                \"recordView\": \"custom:views/admin/my-settings\"\n            }\n        ],\n        \"order\": 20\n    }\n}\n\n```\n\n## label\n\n*string*\n\nA panel label. A translation path: Admin > labels > {label}.\n\n## order\n\n*string*\n\nUsed for ordering panels on the page.\n\n## itemList\n\n*Object[]*\n\n### url\n\n*string*\n\nA link URL. You can use an URL like #Admin/{myName}, in this case you also need to define a recordView.\n\n### label\n\n*string*\n\nAn item (link) label. A translation path: Admin > labels > {label}.\n\n### iconClass\n\n*string*\n\nA CSS class for the icon.\n\n### description\n\n*string*\n\nA translation key for a description text. A translation page: Admin > descriptions > {description}.\n\n### recordView\n\n*string*\n\nA record view. Optional. Needed if you defined the URL like `#Admin/{myName}`. The record view displays settings fields. See [more](../custom-config-parameters.md).\n\n### tabQuickSearch\n\n*boolean*\n\n*As of v9.0.*\n\nMakes available in the navbar tab quick search.\n"
  },
  {
    "path": "docs/development/metadata/app-api.md",
    "content": "# app > api\n\nPath: metadata > app > api.\n\n*As of v7.4.*\n\nDefinitions for API framework.\n\nProvides the ability to add middlewares for all requests, specific routes, controllers and controller actions. Supporting the PSR-15 standard means that it's possible to use 3rd party middlewares, like [these](https://github.com/middlewares/psr15-middlewares). If a middleware you want to use has dependencies in a constructor, use DI binding to resolve them.\n\nExample:\n\n```json\n{\n    \"globalMiddlewareClassNameList\": [\n        \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test1\",\n        \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test2\"\n    ],\n    \"routeMiddlewareClassNameListMap\": {\n        \"get_/:controller\": [\n            \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test3\"\n        ]\n    },\n    \"actionMiddlewareClassNameListMap\": {\n        \"get_/Activities\": [\n            \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test3\"\n        ]\n    },\n    \"controllerMiddlewareClassNameListMap\": {\n        \"Contact\": [\n            \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test4\"\n        ]\n    },\n    \"controllerActionMiddlewareClassNameListMap\": {\n        \"Contact_get_index\": [\n            \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test5\"\n        ],\n        \"Contact_post_create\": [\n            \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test6\"\n        ],\n        \"Contact_put_update\": [\n            \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test7\"\n        ],\n        \"Contact_get_read\": [\n            \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test8\"\n        ],\n        \"Contact_delete_delete\": [\n            \"Espo\\\\Custom\\\\Classes\\\\ApiMiddlewares\\\\Test9\"\n        ]\n    }\n}\n\n```\n\n## globalMiddlewareClassNameList\n\n*class-string<Psr\\Http\\Server\\MiddlewareInterface\\>[]*\n\nA class list of global middlewares. Global middlewares applied for all API requests. Processed before authentication.\n\n## routeMiddlewareClassNameListMap\n\n*Object.<string, class-string<Psr\\Http\\Server\\MiddlewareInterface\\>[]\\>*\n\nMiddlewares for specific routes. Keys are composed in the form: `{method}_{route}`. Processed before authentication.\n\n## actionMiddlewareClassNameListMap\n\n*Object.<string, class-string<Psr\\Http\\Server\\MiddlewareInterface>[]\\>*\n\nMiddlewares for routes with *actionClassName*. Keys are composed in the form: `{method}_{route}`. Processed after authentication.\n\n## controllerMiddlewareClassNameListMap\n\n*Object.<string, class-string<Psr\\Http\\Server\\MiddlewareInterface>[]\\>*\n\nMiddlewares for specific controllers. A controller-name => class-string-list map. Processed after authentication.\n\n## controllerActionMiddlewareClassNameListMap\n\n*Object.<string, class-string<Psr\\Http\\Server\\MiddlewareInterface>[]\\>*\n\nMiddlewares for specific controller actions. Keys are composed in the form: `{ControllerName}_{method}_{actionName}`. Processed after authentication.\n"
  },
  {
    "path": "docs/development/metadata/app-app-params.md",
    "content": "# app > appParams\n\nPath: metadata > app > appParams.\n\n[AppParams framework](../app-params.md) definitions. A name => Object map.\n\n```json\n{\n    \"paramName\": {\n        \"className\": \"Espo\\\\Modules\\\\MyModule\\\\Classes\\\\AppParams\\\\ParamName\"\n    }\n}\n\n```\n\n## className\n\n*string<Espo\\Tools\\App\\AppParam\\>*\n\nAn implementation class name. Should implement `Espo\\Tools\\App\\AppParam` interface.\n"
  },
  {
    "path": "docs/development/metadata/app-authentication-2fa-methods.md",
    "content": "# app > authentication2FAMethods\n\nPath: metadata > app > authentication2FAMethods.\n\nDefinitions for 2-factor authentication methods. A method-name => Object map.\n\n```json\n{\n    \"Totp\": {\n        \"settings\": {\n            \"isAvailable\": true\n        },\n        \"userApplyView\": \"views/user-security/modals/totp\",\n        \"loginClassName\": \"Espo\\\\Core\\\\Authentication\\\\TwoFactor\\\\Totp\\\\TotpLogin\",\n        \"userSetupClassName\": \"Espo\\\\Core\\\\Authentication\\\\TwoFactor\\\\Totp\\\\TotpUserSetup\"\n    }\n}\n\n```\n\n## settings\n\n*Object*\n\n### isAvailable\n\n*bool*\n\nWhether the method should be available as an option at Administration > Authentication > Available 2FA methods.\n\n## userApplyView\n\n*string*\n\nA front-end view for a user when they apply the 2FA method to their account.\n\n## loginClassName\n\n*class-string<Espo\\Core\\Authentication\\TwoFactor\\Login\\>*\n\nA login class. Processes the second step of the login process.\n\n## userSetupClassName\n\n*class-string<Espo\\Core\\Authentication\\TwoFactor\\UserSetup\\>*\n\nA user-setup class.\n\n* Provides needed data for a front-end for a user when they setup the 2FA method.\n* Verifies entered user data before establishing the 2FA method for a user.\n"
  },
  {
    "path": "docs/development/metadata/app-authentication.md",
    "content": "# app > authentication\n\n## beforeLoginHookClassNameList\n\nArray of hook class names. Fired before logging in before credentials are checked. Can throw an exception. Should implement `Espo\\Core\\Authentication\\Hook\\BeforeLogin` interface.\n\n!!! important\n\n    Need to have `__APPEND__` item in the beginning of the array when extending.\n\n## onLoginHookClassNameList\n\n*As of v8.3.*\n\nArray of hook class names. Fired before when a user is found, credentials are fine. Can throw an exception. Should implement `Espo\\Core\\Authentication\\Hook\\OnLogin` interface.\n\n!!! important\n\n    Need to have `__APPEND__` item in the beginning of the array when extending.\n\n## onFailHookClassNameList\n\nArray of hook class names. Fired once logging in is failed. Should implement `Espo\\Core\\Authentication\\Hook\\OnResult` interface.\n\n!!! important\n\n    Need to have `__APPEND__` item in the beginning of the array when extending.\n\n## onSuccessHookClassNameList\n\nArray of hook class names. Fired once logging in is success (not by auth token). Should implement `Espo\\Core\\Authentication\\Hook\\OnResult` interface.\n\n!!! important\n\n    Need to have `__APPEND__` item in the beginning of the array when extending.\n\n## onSuccessByTokenHookClassNameList\n\nArray of hook class names. Fired once logging in by a token is success. Should implement `Espo\\Core\\Authentication\\Hook\\OnResult` interface.\n\n!!! important\n\n    Need to have `__APPEND__` item in the beginning of the array when extending.\n\n## onSecondStepRequiredHookClassNameList\n\nArray of hook class names. Fired once first step is success and second step is required. Should implement `Espo\\Core\\Authentication\\Hook\\OnResult` interface.\n\n!!! important\n\n    Need to have `__APPEND__` item in the beginning of the array when extending.\n"
  },
  {
    "path": "docs/development/metadata/app-cleanup.md",
    "content": "# app > cleanup\n\nA Key-Value map. Defines cleaning up classes. Fired by the *Cleanup* job.\n\nExample:\n\n```json\n\n{\n    \"someName\": {\n        \"className\": \"Espo\\\\SomeImplementation\"\n    }\n}\n```\n\n## className\n\n*class-string<Espo\\Core\\Cleanup\\Cleanup\\>*\n\nAn implementation class. Should implement `Espo\\Core\\Cleanup\\Cleanup` interface.\n"
  },
  {
    "path": "docs/development/metadata/app-client-icons.md",
    "content": "# app > clientIcons\n\nPath: metadata > app > clientIcons.\n\n## classList\n\n*string[]*\n\n*As of v9.1.*\n\nAdditional icon classes. Added icons will be available in the icon picker.\n\nImportant: Prepend the `__APPEND__` value to the array.\n"
  },
  {
    "path": "docs/development/metadata/app-client-navbar.md",
    "content": "# app > clientNavbar\n\nNavbar definitions.\n\n## items\n\n*Object.<string, Object\\>*\n\n*As of v8.1.*\n\nNavbar items (in the top right corner).\n\nExample:\n\n```json\n{\n    \"items\": {\n        \"quickCreate\": {\n            \"view\": \"views/site/navbar/quick-create\",\n            \"class\": \"dropdown hidden-xs quick-create-container\",\n            \"order\": 0,\n            \"disabled\": false\n        }\n    }\n}\n```\n\n### view\n\n*string*\n\nA frontend view.\n\n### class\n\n*string*\n\nA CSS class or multiple classes for the LI tag.\n\n### order\n\n*integer*\n\nAn order position.\n\n### disabled\n\n*bool*\n\nWhether is disabled.\n\n### accessDataList\n\n*Object[]*\n\n*As of v9.1.*\n\nAccess rules. See definitions in JSON schema: metadata/clientDefs.json#/definitions/accessDataList.\n\n## menuItems\n\n*Object.<string, Object\\>*\n\n*As of v8.4.*\n\nMenu items (in the top right corner).\n\nExample:\n\n```json\n{\n    \"menuItems\": {\n        \"myItem\": {\n            \"order\": 0,\n            \"groupIndex\": 5,\n            \"link\": \"#MyItem\",\n            \"labelTranslation\": \"Global.labels.My Item\"\n        }\n    }\n}\n```\n\n### labelTranslation\n\n*string*\n\nA label translation path.\n\n### link\n\n*string*\n\nA link (href).\n\n### order\n\n*integer*\n\nAn order position.\n\n### groupIndex\n\n*integer*\n\nA group index. Groups are separated by a divider.\n\n### disabled\n\n*boolean*\n\nAn item will be hidden.\n\n### handler\n\n*string*\n\nA handler class.\n\n### actionFunction\n\n*string*\n\nAn action function in the handler.\n\n### configCheck\n\n*string*\n\nA config path to check. Path items are separated by a dot. If a config value is not empty, then the action is allowed. The `!` prefix negates the check result.\n\n### accessDataList\n\n*Object[]*\n\nAccess rules. See definitions in JSON schema: metadata/clientDefs.json#/definitions/accessDataList.\n"
  },
  {
    "path": "docs/development/metadata/app-client-record.md",
    "content": "# app > clientRecord\n\nPath: metadata > app > clientRecord.\n\nClient record definitions.\n\n## panels\n\n*Object.<string, Object\\>*\n\n*As of v9.0.*\n\nDetail view panels. Can be referenced from clientDefs > sidePanels/bottomPanels. The panel schema is the same as in clientDefs.\n"
  },
  {
    "path": "docs/development/metadata/app-client-routes.md",
    "content": "# app > clientRoutes\n\nPath: metadata > app > clientRoutes.\n\nFront-end client routes. See more [here](../frontend/controller.md#custom-route).\n"
  },
  {
    "path": "docs/development/metadata/app-client.md",
    "content": "# app > client\n\nPath: metadata > app > client.\n\nGeneral definitions for the front-end client.\n\n## scriptList\n\n*string[]*\n\nJS files to include on the HTML page. Use `__APPEND__` to append custom values w/o removing existing.\n\nExample:\n\n```json\n{\n    \"scriptList\": [\n        \"__APPEND__\",\n        \"client/custom/modules/my-module/my-script.js\"\n    ]\n}\n```\n\n## developerModeScriptList\n\n*string[]*\n\nJS files to include on the HTML page in the developer mode. Use `__APPEND__` to append custom values w/o removing existing.\n\n## linkList\n\n*Object[]*\n\nExample:\n\n```json\n{\n    \"linkList\": [\n        \"__APPEND__\",\n        {\n            \"href\": \"client/custom/fonts/custom-font.woff2\",\n            \"as\": \"font\",\n            \"type\": \"font/woff2\",\n            \"rel\": \"preload\",\n            \"noTimestamp\": true,\n            \"crossorigin\": true\n        }\n    ]\n}\n```\n\nLink tags to include on the HTML page. Use `__APPEND__` to append custom values w/o removing existing.\n\n## cssList\n\n*string[]*\n\nCSS files to include on the HTML page. Use `__APPEND__` to append custom values w/o removing existing.\n\nExample:\n\n```json\n{\n    \"cssList\": [\n        \"__APPEND__\",\n        \"path/to/your/file.css\"\n    ]\n}\n```\n\n## favicon\n\n*string*\n\nA favicon image. SVG or PNG The default value: `client/img/favicon.svg`.\n\n## faviconAlternate\n\n*string*\n\nAn alternate 16px ICO favicon image. The default value: `client/img/favicon.ico`.\n\n"
  },
  {
    "path": "docs/development/metadata/app-complex-expression.md",
    "content": "# app > complexExpression\n\nPath: metadata > app > complexExpression.\n\nDefinitions for the [complex expression](../../user-guide/complex-expressions.md) editor.\n\n## functionList\n\n*Object[]*\n\nFunctions available in the editor when editing a complex expression.\n\nExample:\n\n```json\n{\n    \"functionList\": [\n        \"__APPEND__\",\n        {\n            \"name\": \"MY_CUSTOM_FUNCTION\",\n            \"insertText\": \"MY_CUSTOM_FUNCTION:(VALUE1, VALUE2)\",\n            \"returnType\": \"bool\"\n        }\n    ]\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-config.md",
    "content": "# app > config\n\nPath: metadata > app > config.\n\nApplication config definitions.\n\n## params\n\n*Object.<string, Object\\>\\>*\n\nParameters. A name => params map.\n\nExample:\n\n```json\n{\n\n    \"params\": {\n        \"myParam\": {\n            \"level\": \"default\",\n            \"readOnly\": true\n        },\n        \"smtpPassword\": {\n            \"level\": \"internal\"\n        },\n        \"awsS3Storage\": {\n            \"level\": \"system\"\n        }\n    }\n}\n```\n\n### level\n\n*string*\n\nDefines availability of the config parameter in the front-end. Possible values:\n\n* `default` – available for logged-in users (applied by default) (as of v7.4);\n* `global` – available even before logging in (value is exposed to the world);\n* `system` – never available;\n* `internal` – never available for read, admin can write (useful for passwords, secrets) (as of v7.3);\n* `admin` – available only for admin;\n* `superAdmin` – available only for super-admin.\n\n### readOnly\n\n*boolean*\n\n*As of v7.4.*\n\nDisables the ability to change a parameter value for admin users. Useful for parameters that are supposed to be set either manually by writing into the config file or automatically by the application. \n\n## entityTypeListParamList\n\n*string[]*\n\nA list of config parameters values of which are arrays of entity types. Needed to let the application know what params need to be filtered to remove entity types not available for a user.\n"
  },
  {
    "path": "docs/development/metadata/app-console-commands.md",
    "content": "# app > consoleCommands\n\nPath: metadata > app > consoleCommands.\n\nConsole [commands](../../administration/commands.md). A command-name => defs map.\n\nExample:\n\n```json\n{\n    \"myCommand\": {\n        \"className\": \"Espo\\\\Modules\\\\MyModule\\\\Classes\\\\ConsoleCommands\\\\MyCommand\",\n        \"listed\": true\n    }\n}\n\n```\n\n## className\n\n*class-string<Espo\\Core\\Console\\Command\\>*\n\nA command class. Should implement `Espo\\Core\\Console\\Command` interface.\n\n## listed\n\n*boolean*\n\nWhether the command is listed when running `bin/command`.\n\n## noSystemUser\n\n*boolean*\n\n*As of v8.3.*\n\nDo not load the system user.\n"
  },
  {
    "path": "docs/development/metadata/app-container-services.md",
    "content": "# app > containerServices\n\nPath: metadata > app > containerServices.\n\nDefinitions of [container services](../di.md#container-services). A service-name => defs map.\n\nExample:\n\n```json\n{\n    \"myService1\": {\n        \"className\": \"Espo\\\\Modules\\\\MyModule\\\\MyService1\"\n    },\n    \"myService2\": {\n        \"loaderClassName\": \"Espo\\\\Modules\\\\MyModule\\\\MyService2Loader\"\n    }\n}\n\n```\n\n## className\n\n*class-string*\n\nA service class.\n\n## loaderClassName\n\n*class-string<Espo\\Core\\Container\\Loader\\>*\n\nA service loader class. Should implement `Espo\\Core\\Container\\Loader` interface.\n\n## settable\n\n*boolean*\n\nWhether the service can be set to the container externally (with *set* method).\n"
  },
  {
    "path": "docs/development/metadata/app-currency-conversion.md",
    "content": "# app > currencyConversion\n\nExample:\n\n```json\n{\n    \"entityConverterClassNameMap\": {\n        \"MyEntityType\": \"Espo\\\\Modules\\\\MyModule\\\\Classes\\\\MyEntityCurrencyConverter\"\n    }\n}\n```\n\n## entityConverterClassNameMap\n\n*Object.<string, class-string<Espo\\Tools\\Currency\\Conversion\\EntityConverter\\>\\>*\n\n*As of v7.5.*\n\nEntity currency converters.\n"
  },
  {
    "path": "docs/development/metadata/app-currency.md",
    "content": "# app > currency\n\nPath: metadata > app > currency.\n\nCurrency definitions.\n\n## symbolMap\n\n*Object<string, string\\>*\n\nA currency-code => symbol mapping.\n\nExample:\n\n```json\n{\n    \"EUR\":\"€\",\n    \"GBP\":\"£\"\n}\n```\n\n## list\n\n*string[]*\n\nA list of currencies available in the system. Values defined as 3-letter currency codes in ISO 4217 standard. Use `__APPEND__` to add new currencies w/o deleting existing.\n\nExample:\n\n```json\n\n{\n    \"list\": [\n        \"__APPEND__\",\n        \"COD\"\n    ]\n}\n```\n\n## precisionMap\n\n*Object<string, number\\>*\n\n*As of v9.3.*\n\n\nA currency-code => precision mapping. If not specified, 2 is used as a fallback value.\n\nExample:\n\n```json\n{\n    \"precisionMap\": {\n        \"BHD\": 3\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-database-platforms.md",
    "content": "# app > databasePlatforms\n\nPath: metadata > app > databasePlatforms.\n\n*Object.<string, Object\\>*\n\n*As of v7.4.*\n\nExample:\n\n```json\n{\n    \"Mysql\": {},\n    \"Postgresql\": {}\n}\n```\n\n## dbalConnectionFactoryClass\n\n*class-string<Espo\\Core\\Utils\\Database\\Dbal\\ConnectionFactory\\>*\n\n## detailsProviderClassName\n\n*class-string<Espo\\Core\\Utils\\Database\\Dbal\\DetailsProvider\\>*\n\n## dbalTypeClassNameMap\n\n*Object.<string, class-string<Doctrine\\DBAL\\Types\\Type\\>\\>*\n\n## indexHelperClassName\n\n*class-string<Espo\\Core\\Utils\\Database\\Orm\\IndexHelper\\>*\n\n## columnPreparatorClassName\n\n*class-string<Espo\\Core\\Utils\\Database\\Schema\\ColumnPreparator\\>*\n\n## preRebuildActionClassNameList\n\n*class-string<Espo\\Core\\Utils\\Database\\Schema\\RebuildAction\\>[]*\n\n## postRebuildActionClassNameList\n\n*class-string<Espo\\Core\\Utils\\Database\\Schema\\RebuildAction\\>[]*\n"
  },
  {
    "path": "docs/development/metadata/app-date-time.md",
    "content": "# app > dateTime\n\nPath: metadata > app > dateTime.\n\nDate-time definitions.\n\nExample:\n\n```json\n{\n    \"dateFormatList\": [\n        \"DD.MM.YYYY\",\n        \"MM/DD/YYYY\",\n        \"DD/MM/YYYY\",\n        \"YYYY-MM-DD\",\n        \"DD. MM. YYYY\"\n    ],\n    \"timeFormatList\": [\n        \"HH:mm\",\n        \"hh:mma\",\n        \"hh:mmA\",\n        \"hh:mm A\",\n        \"hh:mm a\"\n    ]\n}\n```\n\n## dateFormatList\n\n*string[]*\n\nA list of date formats available in the system.\n\n## timeFormatList\n\n*string[]*\n\nA list of time formats available in the system.\n"
  },
  {
    "path": "docs/development/metadata/app-default-dashboard-layouts.md",
    "content": "# app > defaultDashboardLayouts\n\nPath: metadata > app > defaultDashboardLayouts.\n\nDefault dashboard layouts.\n\nExample:\n\n```json\n{\n    \"Standard\": [\n        {\n            \"name\": \"My Espo\",\n            \"layout\": [\n                {\n                    \"id\": \"defaultActivities\",\n                    \"name\": \"Activities\",\n                    \"x\": 2,\n                    \"y\": 2,\n                    \"width\": 2,\n                    \"height\": 2\n                },\n                {\n                    \"id\": \"defaultStream\",\n                    \"name\": \"Stream\",\n                    \"x\": 0,\n                    \"y\": 0,\n                    \"width\": 2,\n                    \"height\": 4\n                },\n                {\n                    \"id\": \"defaultTasks\",\n                    \"name\": \"Tasks\",\n                    \"x\": 2,\n                    \"y\": 4,\n                    \"width\": 2,\n                    \"height\": 2\n                }\n            ]\n        }\n    ]\n}\n```\n\nThe *Standard* layout is applied for new users (regular and admin) and when they reset their layout to default.\n"
  },
  {
    "path": "docs/development/metadata/app-default-dashboard-options.md",
    "content": "# app > defaultDashboardOptions\n\nPath: metadata > app > defaultDashboardOptions.\n\nOptions for [default dashboard](app-default-dashboard-layouts.md) dashlets.\n\nExample:\n\n```json\n{\n    \"Standard\": {\n        \"myDashletId\": {\n            \"displayRecords\": 10\n        }\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-email-template.md",
    "content": "# metadata > app > emailTemplate\n\nEmail template definitions.\n\n## placeholders\n\nPlaceholders.\n\nExample:\n\n```json\n\n{\n    \"placeholders\": {\n        \"today\": {\n            \"className\": \"Espo\\\\Tools\\\\EmailTemplate\\\\Placeholders\\\\Today\",\n            \"order\": 0\n        },\n        \"now\": {\n            \"className\": \"Espo\\\\Tools\\\\EmailTemplate\\\\Placeholders\\\\Now\",\n            \"order\": 1\n        },\n        \"currentYear\": {\n            \"className\": \"Espo\\\\Tools\\\\EmailTemplate\\\\Placeholders\\\\CurrentYear\",\n            \"order\": 2\n        }\n    }\n}\n```\n\n### className\n\n*class-string<\\Espo\\Tools\\EmailTemplate\\Placeholder\\>*\n\nAn implementation.\n\n### order\n\n*integer*\n\nAn order position.\n\n## entityLinkMapping\n\n*object.<string, object.<string, string\\>\\>*\n\n*As of v9.2.*\n\nMappings of entity types to links. Used for placeholders.\n\nExample:\n\n```json\n{\n    \"entityLinkMapping\": {\n        \"Opportunity\": {\n            \"Account\": \"account\"\n        }\n    }\n}\n```\n\nIf an Opportunity record is selected as an email parent, *{Account.\\*}* placeholders will be substituted with the Account related to the Opportunity through the *account* link.\n"
  },
  {
    "path": "docs/development/metadata/app-entity-manager-params.md",
    "content": "# app > entityManagerParams\n\n*As of v7.5.*\n\nPath: metadata > app > entityManagerParams\n\nAdditional entity parameters. Defined parameters are available in the entity manager. Global, template type and entity type specific parameters can be defined.\n\nExample:\n\n```json\n{\n    \"Global\": {\n        \"optimisticConcurrencyControl\": {\n            \"location\": \"entityDefs\",\n            \"fieldDefs\": {\n                \"type\": \"bool\",\n                \"tooltip\": true\n            }\n        }\n    },\n    \"MyEntityType\": {\n        \"someParam\": {\n            \"location\": \"scopes\",\n            \"fieldDefs\": {\n                \"type\": \"int\",\n                \"tooltip\": true\n            }\n        }\n    },\n    \"@Event\": {\n        \"someParam\": {\n            \"location\": \"clientDefs\",\n            \"fieldDefs\": {\n                \"type\": \"varchar\",\n                \"tooltip\": true\n            }\n        }\n    }\n}\n\n```\n\n*Global* parameters are available for all entity types. *@Event* defines template specific parameters.\n\nField labels and tooltips should be defined in language data in the *EntityManager* scope.\n\n## location\n\n*string*\n\nA metadata location. Where the parameter  will be stored. Supported values:\n\n* `scopes`\n* `entityDefs`\n* `clientDefs`\n* `recordDefs` (as of v8.0)\n\n## fieldDefs\n\nField definitions (same as [entityDefs > fields](entity-defs.md#fields)). The defined field will be rendered on the entity manager edit view.\n\n!!! note\n\n    Only field types that have one attribute are supported. Meaning that you can't use field type like *link*, *linkParent*, *linkMultiple*.\n\n## groupIndex\n\n*integer*\n\n*As of v10.0.*\n\nAn index to group related parameters into panels.\n"
  },
  {
    "path": "docs/development/metadata/app-entity-manager.md",
    "content": "# app > entityManager\n\nPath: metadata > app > entityManager.\n\n\n## createHookClassNameList\n\n*class-string<Espo\\Tools\\EntityManager\\Hook\\CreateHook\\>[]*\n\n*As of v8.0.*\n\n\nHooks processed when a new custom entity type is created.\n\n\n## deleteHookClassNameList\n\n*class-string<Espo\\Tools\\EntityManager\\Hook\\DeleteHook\\>[]*\n\n*As of v8.0.*\n\nHooks processed when a custom entity type is deleted.\n\n## beforeUpdateHookClassNameList\n\n*class-string<Espo\\Tools\\EntityManager\\Hook\\UpdateHook\\>[]*\n\n*As of v9.0.*\n\nHooks processed before parameters of the entity type are updated. Can be used for validation purpose.\n\n## updateHookClassNameList\n\n*class-string<Espo\\Tools\\EntityManager\\Hook\\UpdateHook\\>[]*\n\n*As of v8.0.*\n\nHooks processed when parameters of the entity type are updated.\n"
  },
  {
    "path": "docs/development/metadata/app-entity-template-list.md",
    "content": "# app > entityTemplateList\n\nPath: metadata > app > entityTemplateList.\n\n*string[]*\n\nA list of entity templates available when creating a new entity type in the Entity Manager tool. Use `__APPEND__` to add new values without deleting existing.\n\nExample:\n\n```json\n[\n   \"Base\",\n   \"BasePlus\",\n   \"Event\",\n   \"Person\",\n   \"Company\"\n]\n```\n"
  },
  {
    "path": "docs/development/metadata/app-entity-templates.md",
    "content": "# app > entityTemplates\n\nPath: metadata > app > entityTemplates\n\n*As of v8.0.*\n\nDefinitions for entity type templates.\n\nExample:\n\n```json\n{\n    \"BasePlus\": {\n        \"entityClassName\": \"Espo\\\\Core\\\\Templates\\\\Entities\\\\BasePlus\",\n        \"repositoryClassName\": \"Espo\\\\Core\\\\Templates\\\\Repositories\\\\BasePlus\"\n    }\n}\n```\n\n## entityClassName\n\n*class-string<Espo\\\\ORM\\\\Entity\\>*\n\nAn entity class to use for a template.\n\n## repositoryClassName\n\n*class-string<Espo\\\\ORM\\\\Repository\\\\Repository\\>*\n\nA repository class to use for a template.\n"
  },
  {
    "path": "docs/development/metadata/app-export.md",
    "content": "# app > export\n\nPath: metadata > app > export.\n\nDefinitions for the Export framework.\n\n## formatList\n\n*string*\n\nAvailable export formats.\n\n## formatDefs\n\n*Object.<string, Object\\>\\>*\n\nDefinitions for export formats. You can define here also custom params specific to your custom format.\n\nExample:\n\n```json\n{\n    \"formatDefs\": {\n        \"csv\": {\n            \"processorClassName\": \"Espo\\\\Tools\\\\Export\\\\Format\\\\Csv\\\\Processor\",\n            \"additionalFieldsLoaderClassName\": \"Espo\\\\Tools\\\\Export\\\\Format\\\\Csv\\\\AdditionalFieldsLoader\",\n            \"mimeType\": \"text/csv\",\n            \"fileExtension\": \"csv\"\n        }\n    }\n}\n```\n\n### processorClassName\n\n*class-string<Espo\\Tools\\Export\\Processor\\>*\n\nA main processing class. Should implement `Espo\\Tools\\Export\\Processor` interface.\n\n### additionalFieldsLoaderClassName\n\n*class-string<Espo\\Tools\\Export\\AdditionalFieldsLoader\\>*\n\nAn additional field loader class. Should implement `Espo\\Tools\\Export\\AdditionalFieldsLoader` interface.\n\n### mimeType\n\n*string*\n\nA mime type of export files.\n\n### fileExtension\n\n*string*\n\nAn extension of export files.\n\n### params\n\nAdditional export parameters.\n\n```json\n\"fields\": {\n    \"myParam\": {\n        \"type\": \"bool\"\n    }\n},\n\"layout\": [\n    [\n        {\"name\": \"myParam\"}\n    ]\n],\n\"dynamicLogic\": {\n    \"myParam\": {\n        \"visible\": {\n            \"conditionGroup\": []\n        }\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-field-processing.md",
    "content": "# app > fieldProcessing\n\nPath: metadata > app > fieldProcessing.\n\nDefinitions for the Field Processing framework.\n\n## readLoaderClassNameList\n\n*class-string<Espo\\Core\\FieldProcessing\\Loader\\>[]*\n\nA list of loader classes. Load additional fields when reading a record. Applied globally for all entity types.\n\n## listLoaderClassNameList\n\n*class-string<Espo\\Core\\FieldProcessing\\Loader\\>[]*\n\nA list of loader classes for lists. Load additional fields when reading a list of record. Applied globally for all entity types.\n\n## saverClassNameList\n\n*class-string<Espo\\Core\\FieldProcessing\\Saver\\>[]*\n\nA list of saver classes. Save additional fields. Applied globally for all entity types.\n"
  },
  {
    "path": "docs/development/metadata/app-file-storage.md",
    "content": "# app > fileStorage\n\nPath: metadata > app > fileStorage.\n\nFile storages.\n\n## implementationClassNameMap\n\n*Object.<string, class-string<Espo\\Core\\FileStorage\\Storage\\>\\>*\n\nImplementation classes for file storages.\n\nExample:\n\n``` json\n{\n    \"implementationClassNameMap\": {\n        \"EspoUploadDir\": \"Espo\\\\Core\\\\FileStorage\\\\Storages\\\\EspoUploadDir\",\n        \"AwsS3\": \"Espo\\\\Core\\\\FileStorage\\\\Storages\\\\AwsS3\"\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-file.md",
    "content": "# app > file\n\nPath: metadata > app > file.\n\n## extensionMimeTypeMap\n\n*Object.<string, string[]\\>*\n\nMime types associated with file extensions.\n\nExample:\n\n```json\n{\n    \"extensionMimeTypeMap\": {\n        \"aac\": [\"audio/aac\"]\n    }\n}\n```\n\n## inlineMimeTypeList\n\n*string[]*\n\nMime types that can be downloaded as inline attachments.\n\nExample:\n\n```json\n{\n    \"inlineMimeTypeList\": [\n        \"__APPEND__\",\n        \"application/some-type\"\n    ]\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-formula.md",
    "content": "# app > formula\n\nPath: metadata > app > formula.\n\nDefinitions for the formula editor.\n\n## functionList\n\n*Object[]*\n\nFunctions available in the editor.\n\nExample:\n\n```json\n{\n    \"functionList\": [\n        \"__APPEND__\",\n        {\n            \"name\": \"myNamespace\\\\myFunction\",\n            \"insertText\": \"myNamespace\\\\myFunction(STRING)\",\n            \"returnType\": \"string\",\n            \"unsafe\": false\n        }\n    ]\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-hook.md",
    "content": "# app > hook\n\nPath: metadata > app > hook.\n\nDefinitions for the [Hook framework](../hooks.md).\n\n## suppressClassNameList\n\n*class-string[]*\n\n*As of v7.4.*\n\nA list of hook classes that should be ignored. Provides the ability to disable built-in hooks.\n"
  },
  {
    "path": "docs/development/metadata/app-image.md",
    "content": "# app > image\n\nPath: metadata > app > image.\n\n## allowedFileTypeList\n\n*string[]*\n\nA list of allowed image mime types. Use `__APPEND__` for extending.\n\n## resizableFileTypeList\n\n*string[]*\n\nA list of image mime types that can be resized to be served in a smaller size. Use `__APPEND__` for extending.\n\n## fixOrientationFileTypeList\n\n*string[]*\n\nA list of image mime types orientation of which can be fixed using exif data.\n\n## previewFileTypeList\n\n*string[]*\n\nA list of image mime types that can be previewed in the File or Attachment-Multiple fields.\n\n## sizes\n\n*Object*\n\nSize dimensions.\n\nExample:\n\n```json\n{\n    \"sizes\": {\n        \"xxx-small\": [18, 18],\n        \"xx-small\": [32, 32],\n        \"x-small\": [64, 64],\n        \"small\": [128, 128],\n        \"medium\": [256, 256],\n        \"large\": [512, 512],\n        \"x-large\": [864, 864],\n        \"xx-large\": [1024, 1024],\n        \"small-logo\": [181, 44]\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-js-libs.md",
    "content": "# app > jsLibs\n\nPath: metadata > app > jsLibs.\n\nJS libraries definitions for the loader.\n\nExample:\n\n```json\n{\n    \"some-lib\": {\n        \"path\": \"client/custom/modules/my-module/lib/some-lib.js\",\n        \"devPath\": \"client/custom/modules/my-module/lib/original/some-lib.js\",\n        \"exportsTo\": \"window\",\n        \"exportsAs\": \"LibObjectName\",\n        \"sourceMap\": false\n    },\n    \"some-umd-lib\": {\n        \"path\": \"client/custom/modules/my-module/lib/some-umd-lib.js\"\n    },\n    \"ace-ext-language_tools\": {\n        \"path\": \"client/lib/ace-ext-language_tools.js\",\n        \"exportsTo\": \"ace.require.define.modules\",\n        \"exportsAs\": \"ace/ext/language_tools\"\n    },\n    \"some-jquery-lib\": {\n        \"path\": \"client/custom/modules/my-module/lib/some-jquery-lib.js\",\n        \"devPath\": \"client/custom/modules/my-module/lib/original/some-jquery-lib.js\",\n        \"exportsTo\": \"$.fn\",\n        \"exportsAs\": \"some-jquery-lib\",\n        \"sourceMap\": true\n    }\n}\n```\n\nLibs can be required in the front-end the following ways:\n\n```js\ndefine('my-module-name', ['some-lib'], (SomeLib) => {});\n```\n\n```js\nimport MyLib from 'my-lib';\n```\n\n```js\nEspo.loader.requirePromise('some-lib').then(SomeLib => {});\n```\n\n## path\n\n*string*\n\nA path to a lib file.\n\n## devPath\n\n*string*\n\nA path to the lib file for the developer mode.\n\n## exportsTo\n\n*string*\n\nTo where the lib is exported. Use dots to define a path.\n\n## exportsAs\n\n*string*\n\nA key name by which the lib is available in a containing object.\n\n## sourceMap\n\n*boolean*\n\nWhether the source map file is available.\n\n## exposeAs\n\n*string*\n\nIf set, the lib will be exposed to the window object. A variable name the lib will be set to. To be used for backward compatibility reasons.\n\n## aliases\n\n*string[]*\n\nAdditional module IDs the lib will be available by. Can be useful for establishing backward compatibility or when another lib requires this lib by a different ID.\n"
  },
  {
    "path": "docs/development/metadata/app-language.md",
    "content": "# app > language\n\nPath: metadata > app > language.\n\nApplication languages.\n\n## list\n\n*string[]*\n\nA list of languages available in the application. The name format: `en_US`.\n\n## aclDependencies\n\n*Object.<string, Object\\>*\n\nRules making language translations available for a user when they don't have access to a scope.\n\nExample:\n\n```json\n{\n    \"aclDependencies\": {\n        \"Lead.options.source\": {\n            \"scope\": \"Opportunity\",\n            \"field\": \"leadSource\"\n        },\n        \"Account.options.industry\": {\n            \"scope\": \"Lead\",\n            \"field\": \"industry\"\n        },\n        \"Meeting\": {\n            \"anyScopeList\": [\"Call\"]\n        }\n    }\n}\n```\n\nKeys are paths to translation data.\n\n### scope\n\n*string*\n\nIf a user has access to the scope, they will have access to translations defined by a key.\n\n### field\n\n*string*\n\nIf a user has access to the field (of a scope), they will have access to translations defined by a key.\n\n### anyScopeList\n\n*string[]*\n\nIf a user has access to any of listed scopes, they will have access to translations defined by a key.\n"
  },
  {
    "path": "docs/development/metadata/app-layouts.md",
    "content": "# app > layouts\n\nPath: metadata > app > layouts.\n\nExample:\n\n```json\n{\n    \"Opportunity\": {\n        \"list\": {\n            \"module\": \"MyModule\"\n        }\n    }\n}\n```\n\n## module\n\n*As of v8.1.*\n\nA module where the default layout is located. Provides the ability to re-define location of layouts for standard entity types.\n"
  },
  {
    "path": "docs/development/metadata/app-link-manager.md",
    "content": "# app > linkManager\n\nPath: metadata > app > linkManager.\n\n## createHookClassNameList\n\n*class-string<Espo\\Tools\\LinkManager\\Hook\\CreateHook\\>*\n\nHooks called when creating a new relationship (in the Entity Manager tool). Use `__APPEND__` for extending.\n\n## deleteHookClassNameList\n\n*class-string<Espo\\Tools\\LinkManager\\Hook\\DeleteHook\\>*\n\nHooks called when deleting a relationship (in the Entity Manager tool). Use `__APPEND__` for extending.\n"
  },
  {
    "path": "docs/development/metadata/app-map-providers.md",
    "content": "# app > mapProviders\n\nPath: metadata > app > mapProviders\n\nExample:\n\n```json\n{\n    \"Google\": {\n        \"renderer\": \"handlers/map/google-maps-renderer\"\n    }\n}\n```\n\n## Renderer\n\n*As of v8.1.*\n\nA frontend renderer. Should extend `handlers/map/renderer`.\n"
  },
  {
    "path": "docs/development/metadata/app-mass-actions.md",
    "content": "# app > massActions\n\nPath: metadata > app > massActions.\n\nDefinitions for the Mass Action framework.\n\nExample:\n\n```json\n{\n    \"myAction\": {\n        \"implementationClassName\": \"Espo\\\\Module\\\\MyModule\\\\Classes\\\\Actions\\\\MyAction\"\n    }\n}\n```\n\n## implementationClassName\n\n*class-string<Espo\\Core\\MassAction\\MassAction\\>*\n\nA main class for the mass action.\n"
  },
  {
    "path": "docs/development/metadata/app-metadata.md",
    "content": "# app > metadata\n\nPath: metadata > app > metadata.\n\nDefinitions for metadata itself.\n\n## frontendHiddenPathList\n\n*Array*\n\nSections of metadata (defined as paths) to be hidden from the front-end.\n\nExample:\n\n```json\n{\n    \"frontendHiddenPathList\": [\n        \"__APPEND__\",\n        [\"app\", \"calendar\", \"additionalAttributeList\"]\n    ]\n}\n```\n\n## frontendNonAdminHiddenPathList\n\n*Array*\n\n*As of v8.0*.\n\nSections of metadata (defined as paths) to be hidden from the front-end for non-admin users.\n\n## aclDependencies\n\n*Object.<string, Object\\>\\>*\n\nRules making a metadata sections available for the user when they don't have access to the scope.\n\nExample:\n\n```json\n{\n    \"aclDependencies\": {\n        \"entityDefs.Lead.fields.source.options\": {\n            \"scope\": \"Opportunity\",\n            \"field\": \"leadSource\"\n        },\n        \"entityDefs.Account.fields.industry.options\": {\n            \"scope\": \"Lead\",\n            \"field\": \"industry\"\n        },\n        \"entityDefs.MyEntityType\": {\n            \"anyScopeList\": [\"AnotherEntityType\"]\n        }\n    }\n}\n```\n\n### scope\n\n*string*\n\nIf the user has access to the scope, they will have access to the metadata section defined by the key.\n\n### field\n\n*string*\n\nIf the user has access to the field (of the scope), they will have access to the metadata section defined by the key.\n\n### anyScopeList\n\n*string[]*\n\n*As of v9.2.5.*\n\nIf the user has access to any of the listed scopes, they will have access to the metadata section defined by the key. \n\n## additionalBuilderClassNameList\n\n*class-string<Espo\\Core\\Utils\\Metadata\\AdditionalBuilder\\>[]*\n\n*As of v8.4.*\n\nAdditional builders. Allows adding conditional metadata.\n"
  },
  {
    "path": "docs/development/metadata/app-orm.md",
    "content": "# app > orm\n\nPath: metadata > app > orm.\n\nDefinitions for [ORM](../orm.md).\n\nExample:\n\n```json\n{\n    \"platforms\": {\n        \"Mysql\": {\n            \"queryComposerClassName\": \"Espo\\\\ORM\\\\QueryComposer\\\\MysqlQueryComposer\",\n            \"pdoFactoryClassName\": \"Espo\\\\ORM\\\\PDO\\\\MysqlPDOFactory\",\n            \"functionConverterClassNameMap\": {\n                \"ABS\": \"Espo\\\\Core\\\\ORM\\\\QueryComposer\\\\Part\\\\FunctionConverters\\\\Abs\"\n            }\n        }\n    }\n}\n```\n\n## platforms\n\n*As of v7.5.*\n\nDefinitions for database platforms.\n\n### queryComposerClassName\n\nclass-string<Espo\\ORM\\QueryComposer\\QueryComposer\\>\n\nA query composer.\n\n### pdoFactoryClassName\n\nclass-string<Espo\\ORM\\PDO\\PDOFactory\\>\n\nA PDO factory.\n\n### functionConverterClassNameMap\n\n*Object.<string, class-string<Espo\\ORM\\QueryComposer\\Part\\FunctionConverter\\>\\>*\n\n[Complex expression](../../user-guide/complex-expressions.md) function converters. Use it to define custom complex expression functions.\n"
  },
  {
    "path": "docs/development/metadata/app-pdf-engines.md",
    "content": "# app > pdfEngines\n\nPath: metadata > app > pdfEngines.\n\nPDF printing engines. An engine-name => defs map.\n\n```json\n{\n    \"MyCustomEngine\": {\n        \"implementationClassNameMap\": {\n            \"entity\": \"Espo\\\\Modules\\\\MyModule\\\\MyCustomEngine\\\\EntityPrinter\",\n            \"collection\": \"Espo\\\\Modules\\\\MyModule\\\\MyCustomEngine\\\\CollectionPrinter\"\n        },\n        \"fontFaceList\": []\n    }\n}\n```\n\n## implementationClassNameMap\n\nImplementations.\n\n### entity\n\n*class-string<Espo\\Tools\\Pdf\\EntityPrinter\\>*\n\n### collection\n\n*class-string<Espo\\Tools\\Pdf\\CollectionPrinter\\>*\n\n## fontFaceList\n\n*string[]*\n\nA list of fonts available for the engine.\n\n## additionalParams\n\n*object*\n\nAdditional engine-wise parameters.\n"
  },
  {
    "path": "docs/development/metadata/app-popup-notifications.md",
    "content": "# app > popupNotifications\n\nPath: metadata > app > popupNotifications.\n\nPopup notifications. A name => defs map.\n\nExample:\n\n```json\n{\n    \"event\": {\n        \"grouped\": true,\n        \"providerClassName\": \"Espo\\\\Modules\\\\Crm\\\\Tools\\\\Activities\\\\PopupNotificationsProvider\",\n        \"useWebSocket\": true,\n        \"portalDisabled\": true,\n        \"view\": \"crm:views/meeting/popup-notification\"\n    }\n}\n```\n\n## grouped\n\n*boolean*\n\n*As of v7.3.*\n\nGrouped popup notifications are fetched with a single API request.\n\n## providerClassName\n\n*class-string<Espo\\Tools\\PopupNotification\\Provider\\>*\n\n*As of v7.3.*\n\nA provider class. Actual only if the *grouped* parameter is set to true.\n\n## useWebSocket\n\n*boolean*\n\nIf WebSocket is configured and the parameter is set to true, notifications won't be polled in the front-end (except once, when the page is loaded). A topic 'popupNotifications.{name}' should be submitted with *Espo\\Core\\WebSocket\\Submission*.\n\n## disabled\n\n*boolean*\n\nDisables.\n\n## portalDisabled\n\n*boolean*\n\nDisables in portals.\n\n## view\n\n*string*\n\nA view for the popup notification.\n\n## interval\n\n*int*\n\nA polling interval in seconds. Actual if *grouped* is false.\n\n## url\n\n*string*\n\nAn API endpoint used for polling. Actual if *grouped* is false.\n"
  },
  {
    "path": "docs/development/metadata/app-portal-container-services.md",
    "content": "# app > portalContainerServices\n\nPath: metadata > app > portalContainerServices.\n\nOverriding of container services for portals. Provides the ability to define custom implementations for portals. The schema is the same as in [containerServices](app-container-services.md).\n"
  },
  {
    "path": "docs/development/metadata/app-reactions.md",
    "content": "# app > reactions\n\nPath: metadata > app > reactions.\n\n*As of v9.0.*\n\n## list\n\nA list of reactions.\n\n*Record[]*\n\nExample:\n\n```json\n{\n    \"list\": [\n        {\n            \"type\": \"Smile\",\n            \"iconClass\": \"far fa-face-smile\"\n        }\n    ]\n}\n```\n\n### type\n\nA reaction type. Must not be longer than 10 characters.\n\n### iconClass\n\nAn icon CSS class.\n"
  },
  {
    "path": "docs/development/metadata/app-rebuild.md",
    "content": "# app > rebuild\n\n## actionClassNameList\n\n*class-string<Espo\\Core\\Rebuild\\RebuildAction\\>*\n\nArray of class names. Actions being processed when the application is being rebuilt. Must implement `Espo\\Core\\Rebuild\\RebuildAction` interface.\n\n"
  },
  {
    "path": "docs/development/metadata/app-record-id.md",
    "content": "# app > recordId\n\nPath: metadata > app > recordId.\n\n*As of v7.4.*\n\n## type\n\n*string*\n\nA type of generated IDs.\n\nAvailable types:\n\n* *id* – 17-character hex (set by default);\n* *uuid4* – UUID v4 (requires setting the *length* to *36* or using *uuid* data type).\n\n## length\n\n*int*\n\nID column length. By default, set to *17*.\n\n## dbType\n\n*string*\n\nAn ID column data type. By default, set to *string* (equivalent to *varchar* in MySQL). Changing this parameter will change types of all ID columns once you run rebuild.\n\nIn MariaDB (as of v10.7) and PostgreSQL it's possible to use *uuid* data type.\n\nBeware of setting the *uuid* data type for instances with data. You will need to migrate all existing ID values to an UUID compatible format (e.g. by applying an MD5 function). Besides database ID columns, you will need to do the same for attachment files and all other references. This may be not a trivial task.\n\nConsider setting the *uuid* type for new instances. If you do it before installation, no any migration work will be needed.\n"
  },
  {
    "path": "docs/development/metadata/app-record.md",
    "content": "# app > record\n\nRecord framework definitions.\n\n## selectApplierClassNameList\n\n*class-string<Espo\\Core\\Select\\Applier\\AdditionalApplier\\>*\n\n*As of v9.0.*\n\nClasses for additional handling of a select query. An entity type is passed to the constructor in `$entityType` parameter.\n\n## createInputFilterClassNameList\n\n*class-string<Espo\\Core\\Record\\Input\\Filter\\>[]*\n\n*As of v10.0.*\n\nCreate input filters.\n\n## updateInputFilterClassNameList\n\n*class-string<Espo\\Core\\Record\\Input\\Filter\\>[]*\n\n*As of v10.0.*\n\nUpdate input filters.\n\n## outputFilterClassNameList\n\n*class-string<Espo\\Core\\Record\\Output\\Filter\\>[]*\n\n*As of v10.0.*\n\nOutput filters.\n\n## beforeReadHookClassNameList\n\n*class-string<Espo\\Core\\Record\\Hook\\ReadHook\\>[]*\n\n*As of v10.0.*\n\nAn array of hooks (applied for API calls).\n\n## earlyBeforeCreateHookClassNameList\n\n*class-string<Espo\\Core\\Record\\Hook\\CreateHook\\>[]*\n*class-string<Espo\\Core\\Record\\Hook\\SaveHook\\>[]*\n\n*As of v10.0.*\n\nAn array of hooks. Applied for API calls, before validation.\n\n## beforeCreateHookClassNameList\n\n*As of v10.0.*\n\n*class-string<Espo\\Core\\Record\\Hook\\CreateHook\\>[]*\n*class-string<Espo\\Core\\Record\\Hook\\SaveHook\\>[]*\n\nAn array of hooks (applied for API calls).\n\n## afterCreateHookClassNameList\n\n*As of v10.0.*\n\n*class-string<Espo\\Core\\Record\\Hook\\CreateHook\\>[]*\n*class-string<Espo\\Core\\Record\\Hook\\SaveHook\\>[]*\n\nAn array of hooks (applied for API calls).\n\n## earlyBeforeUpdateHookClassNameList\n\n*As of v10.0.*\n\n*class-string<Espo\\Core\\Record\\Hook\\UpdateHook\\>[]*\n*class-string<Espo\\Core\\Record\\Hook\\SaveHook\\>[]*\n\nAn array of hooks. Applied for API calls, before validation.\n\n## beforeUpdateHookClassNameList\n\n*As of v10.0.*\n\n*class-string<Espo\\Core\\Record\\Hook\\UpdateHook\\>[]*\n*class-string<Espo\\Core\\Record\\Hook\\SaveHook\\>[]*\n\nAn array of hooks (applied for API calls).\n\n## afterUpdateHookClassNameList\n\n*As of v10.0.*\n\n*class-string<Espo\\Core\\Record\\Hook\\UpdateHook\\>[]*\n*class-string<Espo\\Core\\Record\\Hook\\SaveHook\\>[]*\n\nAn array of hooks (applied for API calls).\n\n## beforeDeleteHookClassNameList\n\n*As of v10.0.*\n\n*class-string<Espo\\Core\\Record\\Hook\\DeleteHook\\>[]*\n\nAn array of hooks (applied for API calls).\n\n## afterDeleteHookClassNameList\n\n*As of v8.2.*\n\n*class-string<Espo\\Core\\Record\\Hook\\DeleteHook\\>[]*\n\nAn array of hooks (applied for API calls).\n\n## beforeLinkHookClassNameList\n\n*As of v10.0.*\n\n*class-string<Espo\\Core\\Record\\Hook\\LinkHook\\>[]*\n\nAn array of hooks (applied for API calls). \n\n## beforeUnlinkHookClassNameList\n\n*As of v10.0.*\n\n*class-string<Espo\\Core\\Record\\Hook\\UnlinkHook\\>[]*\n\nAn array of hooks (applied for API calls).\n\n## afterLinkHookClassNameList\n\n*As of v10.0.*\n\n*class-string<Espo\\Core\\Record\\Hook\\LinkHook\\>[]*\n\nAn array of hooks (applied for API calls).\n\n## afterUnlinkHookClassNameList\n\n*class-string<Espo\\Core\\Record\\Hook\\UnlinkHook\\>[]*\n\n*As of v10.0.*\n\nAn array of hooks (applied for API calls).\n"
  },
  {
    "path": "docs/development/metadata/app-reg-exp-patterns.md",
    "content": "# app > regExpPatterns\n\nPath: metadata > app > regExpPatterns.\n\nPredefined regular expression patterns. A name => defs map. Predefined patterns can be used for field validation.\n\nExample:\n\n```json\n{\n    \"myPattern\": {\n        \"pattern\": \"[0-9A-Za-z_@]+\",\n        \"isSystem\": false\n    }\n}\n```\n\n## pattern\n\n*string*\n\nA pattern.\n\n## isSystem\n\n*boolean*\n\nIf true, the pattern won't be available when defining a validation for a field.\n"
  },
  {
    "path": "docs/development/metadata/app-relationships.md",
    "content": "# app > relationships\n\nPath: metadata > app > relationships.\n\n*Object.<string, Object\\>*\n\nDefinitions of specific named relationships.\n\n*As of v7.4.*\n\nExample:\n\n```json\n{\n    \"attachments\": {\n        \"converterClassName\": \"Espo\\\\Core\\\\Utils\\\\Database\\\\Orm\\\\LinkConverters\\\\Attachments\"\n    }\n}\n```\n\n## converterClassName\n\n*class-string<Espo\\Core\\Utils\\Database\\Orm\\LinkConverter\\>*\n\nConverts metadata link definitions to ORM definitions.\n"
  },
  {
    "path": "docs/development/metadata/app-scheduled-jobs.md",
    "content": "# app > scheduledJobs\n\nPath: metadata > app > scheduledJobs.\n\nScheduled jobs definitions. A name => defs map. Defined scheduled job will be available for the admin when creating a scheduled job.\n\nExample:\n\n```json\n{\n    \"MyJobName\": {\n        \"name\": \"Record Job Name\",\n        \"isSystem\": false,\n        \"scheduling\": \"* * * * *\",\n        \"jobClassName\": \"Espo\\\\Modules\\\\MyModule\\\\MyJob\",\n        \"preparatorClassName\": \"Espo\\\\Modules\\\\MyModule\\\\MyJobPreparator\"\n    }\n}\n```\n\n## name\n\n*string*\n\nA name to be used for job records. Not important.\n\n## isSystem\n\n*boolean*\n\nWhether the job is system internal.\n\n## scheduling\n\n*string*\n\nA default scheduling in crontab notation.\n\n## jobClassName\n\n*class-string<Espo\\Core\\Job\\Job|Espo\\Core\\Job\\JobDataLess\\>*\n\nA job implementation. Should implement either `Job` or `JobDataLess` interfaces. Usage of the former requires having the preparator.\n\n## preparatorClassName\n\n*class-string<Espo\\Core\\Job\\Preparator\\>*\n\nA preparator. Optional. The preparator is called by the application. It serves for creating job records. E.g. for email checking, the preparator creates jobs for each email account.\n"
  },
  {
    "path": "docs/development/metadata/app-select.md",
    "content": "# app > select\n\nPath: metadata > app > select\n\nSelect framework definitions.\n\n## boolFilterClassNameMap\n\n*Object.<string, class-string<Espo\\Core\\Select\\Bool\\Filter\\>\\>*\n\nBool filters available for all entity types.\n\n## orderItemConverterClassNameMap\n\n*Object.<string, class-string<Espo\\Core\\Select\\Order\\ItemConverter\\>\\>*\n\nOrder item converters for field types.\n\n## whereItemConverterClassNameMap\n\n*Object.<string, class-string<Espo\\Core\\Select\\Where\\ItemConverter\\>\\>*\n\nWhere item converters.\n"
  },
  {
    "path": "docs/development/metadata/app-sms-providers.md",
    "content": "# app > smsProviders\n\nPath: metadata > app > smsProviders.\n\nSMS providers. A name => defs map.\n\nExample:\n\n```json\n{\n    \"Twilio\": {\n        \"senderClassName\": \"Espo\\\\Modules\\\\SmsProviders\\\\Twilio\\\\TwilioSender\"\n    }\n}\n```\n\n## senderClassName\n\n*class-string<Espo\\Core\\Sms\\Sender\\>*\n\nA sender class.\n"
  },
  {
    "path": "docs/development/metadata/app-template-helpers.md",
    "content": "# app > templateHelpers\n\nPath: metadata > app > templateHelpers.\n\n[Template helpers](../template-custom-helper.md) for the back-end templating system (used for PDF printing, email templates).\n\n*Object.<string, class-string<Espo\\Core\\Htmlizer\\Helper\\>\\>*\n\nExample:\n\n```json\n{\n    \"MyHelper\": \"Espo\\\\Custom\\\\TemplateHelpers\\\\MyHelper\"\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/app-templates.md",
    "content": "# app > templates\n\nPath: metadata > app > templates.\n\nTemplates (available at Administration > Templates). Usually used for system emails.\n\nExample:\n\n```json\n{\n    \"myTemplateName\": {\n        \"scopeList\": [\n            \"EntityType1\",\n            \"EntityType2\"\n        ],\n        \"module\": \"MyModule\"\n    }\n}\n```\n\n## scopeList\n\n*string[]*\n\nA list of scopes (entity types) for which the template is available.\n\n\n## scope\n\n*string*\n\nA scope (entity types) for which the template is available. Use it if it's needed only for one entity type.\n\n## scopeListConfigParam\n\n*string*\n\nA config parameter defining for which entity types the template is available.\n\n## module\n\n*string*\n\nA module name.\n"
  },
  {
    "path": "docs/development/metadata/app-web-socket.md",
    "content": "# app > webSocket\n\nPath: metadata > app > webSocket.\n\n## categories\n\n*Object*\n\nA category-name => defs map. Define custom WebSocket events here. You can use dots in category names.\n\nExample:\n\n```json\n{\n    \"categories\": {\n        \"myGroupName.myCustomName\": {\n            \"paramList\": [\"scope\", \"id\"],\n            \"accessCheckCommand\": \"AclCheck --userId=:userId --scope=:scope --id=:id --action=read\"\n        }\n    }\n}\n```\n\n### paramList\n\n*string[]*\n\nParameters passed within a topic. E.g. the topic name `myGroupName.myCustomName.Account.someId`. This makes a topic name unique for a specific record. For global events, omit this parameter.\n\n### accessCheckCommand\n\n*string*\n\nA console [command](../../administration/commands.md) that will be used to check whether a topic is allowed for a user when they attempting to subscribe. Parameter placeholders starts with the colon `:`. The `userId` parameter contains a user ID. If access checking is not needed, omit this parameter.\n\n## messagers\n\n*Object.<string, Object\\>*\n\nProvides the ability to implement other messagers rather than the default ZeroMQ. E.g. RabbitMQ.\n\nExample:\n\n```json\n{\n    \"messagers\": {\n        \"ZeroMQ\": {\n            \"senderClassName\": \"Espo\\\\Core\\\\WebSocket\\\\ZeroMQSender\",\n            \"subscriberClassName\": \"Espo\\\\Core\\\\WebSocket\\\\ZeroMQSubscriber\"\n        }\n    }\n}\n```\n\n### senderClassName\n\n*class-string<Espo\\Core\\WebSocket\\Sender\\>*\n\n### subscriberClassName\n\n*class-string<Espo\\Core\\WebSocket\\Subscriber\\>*\n"
  },
  {
    "path": "docs/development/metadata/authentication-methods.md",
    "content": "# authenticationMethods\n\nPath: authenticationMethods > {MethodName}.\n\n## api\n\n*boolean*\n\nDefines that the method is to be used for pure API request, not from the front-end.\n\n## credentialsHeader\n\n*string*\n\n*As of v7.3.*\n\nA header that is supposed to contain credentials. Actual only for API methods.\n\n## login\n\n*As of v7.3.*\n\nA framework providing the ability to call custom code on *Sign-In* button click on the login page.\n\n```json\n{\n    \"login\": {\n        \"handler\": \"my-module:handlers/login\",\n        \"fallback\": true,\n        \"data\": {\n            \"someKey\": \"someValue\"\n        }\n    }\n}\n```\n\nParameters:\n\n* *handler* – a front-end class (should extend the abstract class `handlers/login`).\n* *fallback* – defines that a regular username/password login method is also available on the login page.\n* *fallbackConfigParam* – a config parameter name to be used to check whether fallback login is allowed.\n* *portal* – whether the handler will be available for portals, (bool).\n* *portalConfigParam* – a config parameter name to be used to check whether the handler will be available for portals.\n* *data* – arbitrary data to be passed to the handler. Can be actual as application metadata is not yet available on the login page.\n\nThe handler class should have a method *process* that returns a promise that resolves with HTTP headers. These headers will be sent to the back-end to the `App/user` endpoint.\n\nThe label for the Sign-In button can be defined in the language at `signInLabels` > {MethodName}.\n\nCompatible with 2FA.\n\nOn the login page only global config parameters are available. When implementing a custom login, consider having some global config parameters to access in the handler.\n\n## portalDefault\n\n*boolean*\n\n*As of v7.4.*\n\nIf true, the method will be applied for portals when the method is selected as the default in the settings and the portal does not have a specific authentication provider.\n\n## settings\n\nDefines config parameters and a form on the admin UI. See `application/Espo\\Resources/metadata/authenticationMethods/Oidc.json` for an example.\n\n### isAvailable\n\n*boolean*\n\nWhether the method is available in the settings.\n\n## provider\n\n*As of v7.4.*\n\nParameters for the Authentication Provider entity. Same as in the *settings*. If omitted, then a corresponding parameter from the *settings* is used.\n\n### isAvailable\n\n*boolean*\n\nWhether is available in the Authentication Provider entity.\n"
  },
  {
    "path": "docs/development/metadata/client-defs.md",
    "content": "# clientDefs\n\nPath: metadata > clientDefs > {Scope}\n\nContains parameters used by the front-end.\n\n## controller\n\n*string*\n\nDefines a client controller class.\n\n## collection\n\n*string*\n\nDefines a client record collection class. Optional.\n\nThe default value: `'collection'`. Corresponds to the path `client/src/collection.js`.\n\n## model\n\n*string*\n\nDefines a client record model class. Optional.\n\n## acl\n\n*string*\n\nDefines a client acl class. Optional.\n\nThe default value: `'acl'`. Path `client/src/acl.js`.\n\n## aclPortal\n\n*string*\n\nDefines a client acl class for portals. Optional.\n\nThe default value: `'acl-portal'`. Path `client/src/acl-portal.js`.\n\n## modelDefaultsPreparator\n\n*string*\n\n*As of v8.4.*\n\nDefault attributes preparator for a model when creating a new record. Should extend `handlers/model/defaults-preparator`.\n\n## createDisabled\n\n*boolean*\n\nDisables the ability to create a record from the user interface (from the list view).\n\n## searchPanelDisabled\n\n*boolean*\n\nHides the search panel on the list view.\n\n## searchPanelInPortalDisabled\n\n*boolean*\n\nHides the search panel on the list view in portals.\n\n## textFilterDisabled\n\n*boolean*\n\nDisables text search.\n\n## forceListViewSettings\n\n*boolean*\n\n*As of v9.2.0.*\n\nForce list view settings for non-object entity types.\n\n## views\n\nCustom view classes for list, detail, edit.\n\nExample:\n\n```\n{\n    \"list\": \"custom:views/test/list\",\n    \"detail\": \"custom:views/test/detail\"\n}\n```\n\n## recordViews\n\nCustom record view classes. For list, detail, edit, detailQuick, editQuick, kanban, listRelated.\n\nExample:\n```\n{\n    \"list\": \"custom:views/test/record/list\"\n}\n```\n\n## modalViews\n\nModal view classes.\n\nExample:\n```\n{\n    \"detail\": \"custom:views/test/modal/detail\",\n    \"select\": \"custom:views/test/modal/select-records\"\n}\n```\n\n## listViewModeList\n\n*string[]*\n\nA list view mode list. E.g. *list*, *kanban*.\n\n## viewModeIconClassMap\n\n*object.<string, string\\>*\n\n*As of v8.3.*\n\nView mode icon classes. mode => class map.\n\n## saveErrorHandlers\n\nSave error handlers. See [here](../frontend/save-error-handlers.md).\n\n## viewSetupHandlers\n\nView setup handlers. See [here](https://docs.espocrm.com/development/frontend/view-setup-handlers/).\n\n## inlineEditDisabled\n\n*boolean*\n\nDisable inline edit.\n\n## exportDisabled\n\n*boolean*\n\nDisable the *export* mass-action.\n\n## massUpdateDisabled\n\n*boolean*\n\nDisable the *mass-update* mass action.\n\n## massRemoveDisabled\n\n*boolean*\n\n*As of v7.4.*\n\nDisable the *remove* mass action.\n\n## massFollowDisabled\n\n*boolean*\n\nDisable the *follow* mass-action.\n\n## convertCurrencyDisabled\n\n*boolean*\n\nDisable the *convert-currency* mass-action and action.\n\n## mergeDisabled\n\n*boolean*\n\nDisable the record merge functionality.\n\n## filterList\n\nA list of primary filters.\n\nExample:\n\n```json\n{\n    \"filterList\": [\n        {\n            \"name\": \"planned\"\n        },\n        {\n            \"name\": \"held\",\n            \"style\": \"success\"\n        },\n        {\n            \"name\": \"someFilter\",\n            \"accessDataList\": []\n        },\n        {\n            \"name\": \"notAvailableOnListViewFilter\",\n            \"aux\": true\n        }\n    ]\n}\n```\n\n## boolFilterList\n\nA list of bool filters.\n\nExample:\n\n```json\n{\n    \"boolFilterList\": [\"onlyMy\"]\n}\n```\n\nExample:\n\n```json\n{\n    \"boolFilterList\": [\n        {\n            \"name\": \"onlyMy\",\n            \"accessDataList\": []\n        }\n    ]\n}\n```\n\n## defaultFilterData\n\nA default filter data.\n\n## selectDefaultFilters\n\nA default filter on the select-records modal.\n\n```json\n{\n    \"selectDefaultFilters\": {\n        \"filter\": \"myPrimaryFilter\"\n    }\n}\n```\n\n## rowActionList\n\n*As of v8.1.*\n\nRow actions for the main list view.\n\nExample:\n\n```json\n{\n    \"rowActionList\": [\n        \"moveToTop\",\n        \"moveUp\",\n        \"moveDown\",\n        \"moveToBottom\"\n    ]\n}\n```\n\nUse `\"__APPEND__\"` for extending.\n\n## rowActionDefs\n\n*As of v8.1.*\n\nRow action definitions.\n\nExample:\n\n```json\n{\n    \"rowActionDefs\": {\n        \"moveToTop\": {\n            \"label\": \"Move to Top\",\n            \"handler\": \"crm:handlers/knowledge-base-article/move\",\n            \"acl\": \"edit\"\n        }\n}\n```\n\n### handler\n\n*string*\n\nA handler. Should extend handlers/row-action.\n\n### label\n\n*string*\n\nA translatable label.\n\n### labelTranslation\n\n*string*\n\nA label translation path.\n\n### acl\n\n*\"edit\"|\"delete\"*\n\nRequired access.\n\n### groupIndex\n\n*integer*\n\nA group index. Starts from 0. As of v8.3.0.\n\n### nameAttribute\n\n*string*\n\n*As of v9.1.*\n\nAn entity attribute to be used to display the record name on views.\n    \n## menu\n\nTop-right menu for views (list, detail, edit). Available types: *buttons*, *dropdown*.\n\nExample:\n\n```json\n{\n    \"menu\": {\n        \"detail\": {\n            \"buttons\": [\n                {\n                    \"labelTranslation\": \"Campaign.links.trackingUrls\",\n                    \"link\": \"#CampaignTrackingUrl\",\n                    \"acl\": \"read\",\n                    \"aclScope\": \"CampaignTrackingUrl\"\n                }\n            ],\n            \"dropdown\": [\n                {\n                    \"label\": \"Some Action\",\n                    \"acl\": \"edit\",\n                    \"aclScope\": \"SomeScope\",\n                    \"action\": \"someAction\"\n                }\n            ]\n        }\n    }\n}\n```\n\nSee [more](../custom-buttons.md).\n\n## sidePanels\n\nDefinitions of side-panels for views (detail, edit, detailSmall, editSmall). Defined panels will be available in the layout manager.\n\nExample: \n\n```json\n{\n    \"sidePanels\": {\n        \"detail\": [\n            {\n                \"name\": \"attendees\",\n                \"label\": \"Attendees\",\n                \"view\": \"crm:views/meeting/record/panels/attendees\",\n                \"options\": {\n                    \"fieldList\": [\n                        \"users\",\n                        \"contacts\",\n                        \"leads\"\n                    ]\n                },\n                \"isForm\": true,\n                \"notRefreshable\": true\n            }\n        ]\n    }\n}\n```\n\n### isForm\n\n*boolean*\n\nNeeded for a proper UI styling when the panel contains a form.\n\n### notRefreshable\n\n*boolean*\n\nNot refreshable (when clicking on the header).\n\n### options\n\n*object*\n\nOptions to pass to the panel view.\n\n### accessDataList\n\nAccess control defs.\n      \n## bottomPanels\n\nDefinitions of bottom-panels for views. The same as sidePanels.\n\n## relationshipPanels\n\nParameters to be applied for specific relationship panels. Some parameters are also applied for link, link-multiple fields, e.g. *selectPrimaryFilterName*, *selectBoolFilterList*, *selectHandler*.\n\nExample:\n\n```json\n{\n    \"relationshipPanels\": {\n        \"linkName\": {\n            \"view\": \"my-module:views/panels/panel-view\",\n            \"recordListView\": \"my-module:views/record/list\",\n            \"rowActionsView\": \"my-module:views/record/row-actions/view\",\n            \"label\": \"Panel Label\",\n            \"readOnly\": false,\n            \"selectDisabled\": false,\n            \"createDisabled\": false,\n            \"viewDisabled\": false,\n            \"unlinkDisabled\": false,\n            \"editDisabled\": false,\n            \"removeDisabled\": false,\n            \"orderBy\": \"someField\",\n            \"orderDirection\": \"asc\",\n            \"mandatoryAttributeList\": [\"status\"],\n            \"createRequiredAccess\": \"read\",\n            \"selectRequiredAccess\": \"edit\",\n            \"selectPrimaryFilterName\": \"filterName\",\n            \"selectBoolFilterList\": [\"onlyMy\"],\n            \"filterList\": [\"all\", \"filterName\"],\n            \"layout\": \"listLayoutName\",\n            \"selectMandatoryAttributeList\": [\"accountId\", \"accountName\"],\n            \"selectOrderBy\": \"createdAt\",\n            \"selectOrderDirection\": \"asc\"\n        }\n    }\n}\n```\n\n### layout\n\nA layout name or a layout defined as an array.\n\n### createDisabled\n\n*boolean*\n\nDisable the ability to create related records.\n\n### selectDisabled\n\n*boolean*\n\nDisable the ability to select related records.\n\n### viewDisabled\n\n*boolean*\n\nDisable the ability to view related records in a modal.\n\n### unlinkDisabled\n\n*boolean*\n\nDisable the ability to unlink related records.\n\n### editDisabled\n\n*boolean*\n\n*As of v8.1.*\n\nHide the edit action.\n\n### removeDisabled\n\n*boolean*\n\n*As of v8.1.*\n\nHide the remove action.\n\n### label\n\n*string*\n\nA custom translatable label.\n\n### createRequiredAccess\n\n*string*\n\nAccess (to a current entity type) required for creating related records.\n\n### selectRequiredAccess\n\n*string*\n\nAccess (to a current entity type) required for selecting related records.\n\n### selectPrimaryFilterName\n\n*string*\n\nA primary filter applied when selecting records.\n\n### selectBoolFilterList\n\n*string[]*\n\nBool filters applied when selecting records.\n\n### primaryFilter\n\n*string*\n\n*As of v8.1.*\n\nA default primary filter.\n\n### filterList\n\n*string[]*\n\nFilters available in the dropdown.\n\n### orderBy\n\n*string*\n\nAn order-by field.\n\n### orderDirection\n\n*string*\n\n`\"asc\"` or `\"desc\"`.\n\n### mandatoryAttributeList\n\n*string[]*\n\n*As of v9.0.*\n\nMandatory attributes to be selected in the list.\n\n### selectHandler\n\n*string*\n\nA select handler for providing filters when selecting related records. Should have a method *getFilters* returning a promise.\n\nOptionally, extend from `handlers/select-related`.\n\n### createHandler\n\n*string*\n\nA create handler. Provides attributes when creating a new related record. Should have a method *getAttributes* returning a promise.\n\nOptionally, extend from `handlers/create-related`.\n\n### selectFieldHandler\n\n*string*\n\n*As of v8.0.*\n\nA handler called when change a link field. Only for belongs-to and has-one relations. Should have *getAttributes* and *getClearAttributes* methods.\n\n### selectMandatoryAttributeList\n\n*string[]*\n\n*As of v8.0.*\n\nAttributes to be selected when selecting records.\n\n### selectLayout\n\n*string*\n\n*As of v8.0.3*\n\nA list layout name for the select dialog.\n\n### selectOrderBy\n\n*string*\n\n*As of v8.2.*\n\nA field to order by when selecting records.\n\n### selectOrderDirection\n\n*\"asc\"|\"desc\"*\n\n*As of v8.2.*\n\nAn direction to order by when selecting records.\n\n### rowActionList\n\n*string[]*\n\n*As of v8.1.*\n\nRow actions.\n\n### syncWithModel\n\n*boolean*\n\n*As of v8.1.*\n\nRe-fetch records when the parent model is saved or refreshed by WebSocket.\n\n### syncBackWithModel\n\n*boolean*\n\n*As of v9.1.6.*\n\nRe-fetch the parent model when the relationship is updated. Ignored if WebSocked is enabled.\n\n### massSelect\n\n*bool*\n\nEnables mass select.\n\n### createAttributeMap\n\n*Object.<string, string\\>*\n\nAttributes to carry over to a related record when creating. Mapping Parent => Related.\n\n### buttonList\n\n*Record[]*\n\n*As of v8.4.*\n\nHeader buttons.\n\nParameters:\n\n* name\n* label\n* handler\n* actionFunction\n* acl\n\n### actionList\n\n*Record[]*\n\n*As of v8.4.*\n\nHeader dropdown items.\n\nParameters:\n\n* name\n* label\n* handler\n* actionFunction\n* acl\n\n### viewModalView\n\n*string*\n\nA modal view for viewing relationships in a modal dialog.\n\n### allResultDisabled\n\n*boolean*\n\n*As of v9.2.*\n\nDisable the ability to select all results. Important for non-standard relationship panels.\n\n## additionalLayouts\n\nAdditional layouts for a scope.\n\n```json\n{\n    \"additionalLayouts\": {\n        \"detailConvert\": {\n            \"type\": \"detail\"\n        },\n        \"listForAccount\": {\n            \"type\": \"listSmall\"\n        },\n        \"listForContact\": {\n            \"type\": \"listSmall\"\n        }\n    }\n}\n```\n    \n## massActionList\n\n*string[]*\n\nMass actions.\n\n## checkAllResultMassActionList\n\n*string[]*\n\nMass actions available when selecting all results.\n\n## massActionDefs\n\n*Object.<string, mixed\\>*\n\nDefinitions for mass actions. See [more](../custom-buttons.md#mass-action-in-list-view).\n\n### handler\n\n*string*\n\nA handler class for the mass action.\n\n### initFunction\n\n*string*\n\nAn init function of the handler.\n\n### configCheck\n\n*?string*\n\nA config path (separated by the `.`) to check whether the action is enabled. The `!` prefix reverts.\n\n### aclScope\n\n*?string*\n\nA scope access to which is required for the action.\n\n### acl\n\n*?string*\n\nAn acl action access to which is required for the action.\n\n## detailActionList\n\n*Object[]*\n\nDetail view actions (available from the dropdown next to the *Edit* button).\n\n### name\n\n*string*\n\nAn action name.\n\n### label\n\nA translatable label.\n\n### handler\n\n*string*\n\nA handler class for the action.\n\n### initFunction\n\n*string*\n\nAn init function of the handler.\n\n### checkVisibilityFunction\n\n*?string*\n\nThe handler function that checks whether the action is available. Should return a boolean value. Called on model sync.\n\n### configCheck\n\n*?string*\n\nA config path (separated by the `.`) to check whether the action is enabled. The `!` prefix reverts.\n\n### aclScope\n\n*?string*\n\nA scope access to which is required for the action.\n\n### acl\n\n*?string*\n\nAn acl action access to which is required for the action.\n\n### groupIndex\n\n*number*\n\nA group index. 0 – is the first group. Groups are separated by a divider. As of v8.3.0.\n\n## modalDetailActionList\n\n*Object[]*\n\nModal detail view actions. Parameters are the same as for *detailActionList*.\n\n## iconClass\n\nA scope icon class.\n\nExample: `\"fas fa-chess-king\"`\n\n## color\n\nScope color in HEX.\n\n## kanbanViewMode\n\n*boolean*\n\nWhether the scope has the kanban view mode on the list view.\n\n## isExpandedByDefault\n\n*boolean*\n\nActual for category scopes (e.g. DocumentFolder). If true, then by default it will be in expanded mode.\n\n## dynamicLogic\n\n[Dynamic logic](../../administration/dynamic-logic.md) definitions making a form dynamic.\n\n```json\n{\n    \"dynamicLogic\": {\n        \"fields\": {\n            \"fieldName\": {\n                \"visible\": {\n                    \"conditionGroup\": []\n                },\n                \"required\": {\n                    \"conditionGroup\": []\n                },\n                \"readOnly\": {\n                    \"conditionGroup\": []\n                }\n            }\n        },\n        \"panels\": {\n            \"panelName\": {\n                \"visible\": {\n                    \"conditionGroup\": []\n                }\n            }\n        }\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/dashlets.md",
    "content": "# dashlets\n\nPath: metadata > dashlets > {DashletName}.\n\nDefines a dashlet.\n\n## view\n\n*string*\n\nA front-end view for a dashlet.\n\n## aclScope\n\n*string*\n\nA scope access to which is required to have access to the dashlet.\n\n## accessDataList\n\n*module:utils~AccessDefs[]*\n\nAccess data list defining access to the dashlet for a user in the frontend (additionally to *aclScope*).\n\n```\n/**\n * @typedef {Object} module:utils~AccessDefs\n *\n * @property {'create'|'read'|'edit'|'stream'|'delete'|null} action An ACL action to check.\n * @property {string|null} [scope] A scope to check.\n * @property {string[]} [portalIdList] A portal ID list. To check whether a user in one of portals.\n * @property {string[]} [teamIdList] A team ID list. To check whether a user in one of teams.\n * @property {boolean} [isPortalOnly=false] Allow for portal users only.\n * @property {boolean} [inPortalDisabled=false] Disable for portal users.\n * @property {boolean} [isAdminOnly=false] Allow for admin users only.\n */\n```\n\nExample:\n\n```json\n{\n    \"accessDataList\": [\n        {\n            \"inPortalDisabled\": true\n        }\n    ]\n}\n```\n\n## options\n\n*Object*\n\nDashlet options definitions.\n\n### view\n\nAn options view. Can be omitted.\n\n### fields\n\n*Object*\n\nDefinitions of dashlet options fields. The format is the same as in entityDefs > {EntityType} > fields.\n\n### defaults\n\n*Object*\n\nDefault options values.\n\n### layout\n\nAn options layout.\n\nExample:\n\n```json\n{\n    \"options\": {\n        \"layout\": [\n            {\n                \"rows\": [\n                    [\n                        {\"name\": \"title\"},\n                        false\n                    ]\n                ]\n            }\n        ]\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/metadata/entity-acl.md",
    "content": "# entityAcl\n\nRestrictions for fields and links can be defined here.\n\nPath: metadata > entityAcl > {EntityType}.\n\nExample:\n\n```json\n{\n    \"fields\": {\n        \"someFieldName\": {\n            \"readOnly\": true\n        },\n        \"anotherFieldName\": {\n            \"forbidden\": true\n        }\n    },\n    \"links\": {\n        \"someLinkName\": {\n            \"nonAdminReadOnly\": true\n        }\n    }\n    \"systemWriteForbidden\": false\n}\n```\n\nAvailable params (all are booleans):\n\n* forbidden – totally forbidden;\n* internal – reading forbidden, writing allowed;\n* onlyAdmin – forbidden for non admin users;\n* readOnly – read-only for all users;\n* nonAdminReadOnly – read-only for non-admin users.\n\n## systemWriteForbidden\n\n*boolean*\n\n*As of v10.0.0.*\n\nRestricts record update and removal in formula.\n"
  },
  {
    "path": "docs/development/metadata/entity-defs.md",
    "content": "# entityDefs\n\nPath: metadata > entityDefs > {EntityType}.\n\nContains entity definitions, particularly fields, links and indexes.\n\n```json\n{\n\n    \"fields\": {},\n    \"links\": {},\n    \"indexes\": {},\n    \"collection\": {}\n}\n```\n\n## fields\n\nA field-name => parameters map.\n\n\n```json\n\n{\n    \"fields\": {\n        \"myField\": {\n            \"type\": \"varchar\",\n            \"someParam\": \"someValue\"\n        }\n    }\n}\n```\n\nHere are defined: common parameters as well as parameters specific for a field type (defined in metadata > fields > {fieldType} > params).\n\nCommon parameters are listed below.\n\n### type\n\n*string*\n\nA field type.\n\n### notStorable\n\n*boolean*\n\nThe field will be marked as not-storable, a DB column won't be created.\n\n### orderDisabled\n\n*boolean*\n\n*As of v8.3.*\n\nDisables the ability to sort by the field.\n\n### readOnly\n\n*boolean*\n\nRead-only fields are stripped from a payload received from the front-end. Fields are not editable.\n\n\n### view\n\n*string*\n\nA custom field view. If not specified, then a value from metadata > fields > {fieldType} > view is used.\n\n### index\n\n*boolean*\n\nTo create a DB index for the field.\n\n### dbType\n\n*string*\n\nOverrides the type of the DB column.\n\n### disabled\n\n*boolean*\n\nDisables the field.\n\n### utility\n\n*As of v8.0.*\n\n*boolean*\n\nThe field will be hidden from the user on the UI whenever possible.\n\n### tooltip\n\n*boolean|string*\n\nEnable a tooltip for the field. A tooltip text is taken from the language by: {EntityType} > tooltips > {fieldName}.\n\nIf defined as a string, then text will be taken from the language by a path {EntityType} > tooltips > {value}.\n\nIf defined as a string containing a dot character, then parsed with {EntityType}.{key} format, a text will be taken by a path {EntityType} > tooltips > {key} (as of v8.0).\n\n### validatorClassName\n\n*class-string*\n\nA field validator. Legacy, consider using *validatorClassNameMap* or *validatorClassNameList*.\n\n### validatorClassNameMap\n\n*Object.<string, class-string\\>*\n\n*As of v7.4.*\n\nValidators defined as validation-type => class-name map. Classes should implement `Espo\\Core\\FieldValidation\\Validator` interface. If not defined for a type, metadata > fields > {fieldType} > validatorClassNameMap > {type} is used.\n\nExample:\n\n```json\n{\n    \"validatorClassNameMap\": {\n        \"required\": \"Espo\\\\Modules\\\\MyModule\\\\Classes\\\\FieldValidators\\\\MyField\\\\RequiredValidator\"\n    }\n}\n```\n\nSee more about [field validation](fields.md#validationlist).\n\n### validatorClassNameList\n\n*class-string[]*\n\nA list of additional validators. Should implement `Espo\\Core\\FieldValidation\\Validator` interface.\n\n### forceValidation\n\n*boolean*\n\n*As of v8.2.*\n\nAlways to perform validation, regardless whether field values are sent.\n\n### validationDependsOnFieldList\n\n*string[]*\n\n*As of v10.0.*\n\nChange of any of the listed fields triggers the validation for the field in question.\n\n### validationList[]\n\n*string*\n\nA custom validation list for the field. Use this parameter to re-define validations applied for a specific field. By default, [validations](fields.md#validationlist) for a field type are applied.\n\n### mandatoryValidationList\n\n*string[]*\n\nA custom mandatory validation list for the field. Use this parameter to re-define mandatory validations applied for a specific field. By default, [mandatory validations](fields.md#mandatoryvalidationlist) for a field type are applied.\n\n### suppressValidationList\n\n*string[]*\n\n*As of v8.0.*\n\nA validation list to be bypassed for the field.\n\n### sanitizerClassNameList\n\n*class-string[]*\n\n*As of v8.1.*\n\nA list of input sanitizers. Should implement `Espo\\Core\\FieldSanitize\\Sanitizer` interface.\n\n### sanitizerSuppressClassNameList\n\n*class-string[]*\n\n*As of v8.3.*\n\nA list of input sanitizers to be by-passed.\n\n### customizationDisabled\n\n*boolean*\n\nDisables the ability to customize the field in the Entity Manager tool.\n\n### dynamicLogicDisabled\n\n*boolean*\n\nDynamic logic cannot be customized.\n\n### dynamicLogicConditionTypeList\n\n*string[]*\n\n*As of v10.0.*\n\nOverrides Dynamic Logic condition types.\n\n### fieldManagerParamList\n\n*string[]*\n\nParameters available in the Entity Manager tool when editing the field. Specify an empty array to disable all parameters.\n\n### fieldManagerAdditionalParamList\n\n*object[]*\n\nAdditional field parameters available in the Entity Manager.\n\n### layoutAvailabilityList\n\n*string[]*\n\nA list of layout types available for the field. Specify an empty array to disable in all layouts. If not specified, then no limitation is applied.\n\nExample:\n\n```json\n{\n    \"layoutAvailabilityList\": [\n        \"list\",\n        \"detail\"\n    ]\n}\n```\n\n### layoutIgnoreList\n\n*string[]*\n\n*As of v8.2.*\n\nA list of layout types not available for the field.\n\n### textFilterDisabled\n\n*boolean*\n\nTo disable the ability to add the field to text filters (in the Entity Manager tool).\n\n### directAccessDisabled\n\n*boolean*\n\nIndicates that the field value is not accessed or written directly but through some additional logic. The field won't be available in PDF Templates, Email Templates and some other tools.\n\n### directUpdateDisabled\n\n*boolean*\n\nIndicates that updating the field directly is not possible. The parameter is not needed if *directAccessDisabled* is true.\n\n### directUpdateEnabled\n\n*boolean*\n\n*As of v9.3.*\n\nIndicates that updating the field directly is possible. To be used if directAccessDisabled is true to indicate that update is possible.\n\n### filtersEnabled\n\n*boolean*\n\n*As of v9.2.*\n\nIndicates that the field can be used in filters regardless of directAccessDisabled being set to true. To be used only with directAccessDisabled.\n\n### listColumnEnabled\n\n*boolean*\n\nIndicated that the field can be used in list columns regardless of directAccessDisabled being set to true.\n\n### importDisabled\n\n*boolean*\n\nTo disable the ability to import the field.\n\n### importEnabled\n\n*boolean*\n\n*As of v9.3.*\n\nIndicates that import for the field is allowed even if directAccessDisabled or directUpdateDisabled are true.\n\n### massUpdateDisabled\n\n*boolean*\n\n*As of v8.4.*\n\nTo mass-update for the field.\n\n### exportDisabled\n\n*boolean*\n\nTo disable the ability to export the field.\n\n### apiSpecDisabled\n\n*boolean*\n\n*As of v9.3.*\n\nDo not print the field in the OpenAPI spec.\n\n### isPersonalData\n\n*boolean*\n\nWhether the field may contain personal data.\n\n### valueFactoryClassName\n\n*class-string<Espo\\ORM\\Value\\ValueFactory\\>*\n\nA factory for [value objects](../orm-value-objects.md). For field types it's defined at metadata > fields. Here you can define a factory for a specific field.\n\n### attributeExtractorClassName\n\n*class-string<Espo\\ORM\\Value\\AttributeExtractor\\>*\n\nAn extractor for [value objects](../orm-value-objects.md). For field types it's defined at metadata > fields. Here you can define an extractor for a specific field.\n\n### duplicatorClassName\n\n*class-string<Espo\\Core\\Record\\Duplicator\\FieldDuplicator\\>*\n\nDuplicates attributes of a field. Some fields can require some processing when an entity is being duplicated.\n\n### duplicateIgnore\n\n*boolean*\n\nDo not carry over a field value when duplicating an entity.\n\n### optimisticConcurrencyControlIgnore\n\n*boolean*\n\n*As of v9.1.*\n\nIgnore optimistic concurrency control.\n\n### additionalAttributeList\n\n*string[]*\n\nAdditional attributes for a field. Attribute name will be derived by concatenating the specified name with the field name.\n\n### fullNameAdditionalAttributeList\n\n*string[]*\n\nAdditional attributes for a field. As of v9.2.\n\n### dependeeAttributeList\n\n*string[]*\n\nDependee attributes.\n\n### loaderClassName\n\n*class-string<Espo\\Core\\FieldProcessing\\Loader>*\n\n*As of v9.1.*\n\nLoads the field value. Can be used to load non-storable fields (not stored in the entity table).\n\nWithin an API request (Record service), processed after *readLoaderClassNameList*.\n\n### select\n\n*Object*\n\nA custom [complex expression](../../user-guide/complex-expressions.md) to be used for the field when reading from DB. It's possible to define *leftJoins* and *joins* that are needed to be applied when the field is being selected.\n\nExample:\n\n```json\n{\n    \"fields\": {\n        \"myField\": {\n            \"type\": \"float\",\n            \"readOnly\": true,\n            \"notStorable\": true,\n            \"select\": {\n                \"select\": \"DIV:(MUL:(amount, probability, someTableAlias.rate), 100)\",\n                \"leftJoins\": [\n                    [\n                        \"SomeTable\",\n                        \"someTableAlias\",\n                        {\"someTableAlias.id:\": \"amountCurrency\"}\n                    ]\n                ]\n            }\n        }\n    }\n}\n```\n\nParameters:\n\n* select – *string* – select expressions;\n* leftJoins – *Array[]* – left joins to apply;\n* joins – *Array[]* – joins to apply;\n\n### order\n\n*Object*\n\nCustom [complex expressions](../../user-guide/complex-expressions.md) to be used when ordering by the field. It's possible to define *leftJoins* and *joins* that are needed to be applied.\n\nExample:\n\n```json\n{\n    \"fields\": {\n        \"myField\": {\n            \"type\": \"float\",\n            \"readOnly\": true,\n            \"notStorable\": true,\n            \"order\": {\n                \"order\": [\n                    [\"DIV:(MUL:(amount, probability, someTableAlias.rate), 100)\", \"{direction}\"]\n                ],\n                \"leftJoins\": [\n                    [\n                        \"SomeTable\",\n                        \"someTableAlias\",\n                        {\"someTableAlias.id:\": \"amountCurrency\"}\n                    ]\n                ]\n            }\n        }\n    }\n}\n```\n\nParameters:\n\n* order – *Array[]* – order expressions;\n* leftJoins – *Array[]* – left joins to apply;\n* joins – *Array[]* – joins to apply;\n* additionalSelect – *string[]* – additional columns to be selected when order by the field is applied.\n\n### where\n\n*Object*\n\nCustom where clause to be used when the field is met in a provided where-clause. It's possible to define *leftJoins* and *joins* that are needed to be applied. Every comparison operation that you need to support should have its own definitions.\n\nSupported comparison keys:\n\n* `=`\n* `<>`\n* `<`\n* `>`\n* `<=`\n* `>=`\n* `IS NULL`\n* `IS NOT NULL`\n* `LIKE`\n* `NOT LIKE`\n* `IN`\n* `NOT IN`\n* `= TRUE`\n* `= FALSE`\n\nSupported parameters:\n\n* whereClause – where-clause;\n* leftJoins – *Array[]* – left joins to apply;\n* joins – *Array[]* – joins to apply;\n* distinct – bool – apply DISTINCT to the query;\n\nExample:\n\n```json\n{\n    \"fields\": {\n        \"myField\": {\n            \"type\": \"float\",\n            \"readOnly\": true,\n            \"notStorable\": true,\n            \"where\": {\n                \"=\": {\n                    \"whereClause\": {\n                        \"DIV:(MUL:(amount, probability, someTableAlias.rate), 100)=\": \"{value}\"\n                    },\n                    \"leftJoins\": [\n                        [\n                            \"SomeTable\",\n                            \"someTableAlias\",\n                            {\"someTableAlias.id:\": \"amountCurrency\"}\n                        ]\n                    ]\n                },\n                \"IS NULL\": {\n                    \"whereClause\": {\n                       \"IS_NULL:(amount)\": true\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n### massUpdateActionList\n\n*string[]*\n\nActions for mass update.\n\n### notLockable\n\n*boolean*\n\nThe field is not locked when the record is locked. As of v10.0.\n\n## links\n\nA link-name => parameters map.\n\nExample:\n\n```json\n\n{\n    \"links\": {\n        \"myLink1\": {\n            \"type\": \"belongsTo\",\n            \"entity\": \"ForeignEntity\",\n            \"foreign\": \"foreignLink1\"\n        },\n        \"myLink2\": {\n            \"type\": \"hasMany\",\n            \"entity\": \"ForeignEntity\",\n            \"foreign\": \"foreignLink2\"\n        }\n    }\n}\n```\n\nParameters are listed below.\n\n### type\n\n*string*\n\nA link type.\n\nAvailable types:\n\n* belongsTo\n* hasMany\n* hasOne\n* belongsToParent\n* hasChildren\n\n### entity\n\n*string*\n\nA foreign entity type.\n\n### foreign\n\n*string*\n\nA foreign link name.\n\n\nParameters for specific types are listed below.\n\n### noJoin\n\n*boolean*\n\n*(available for belongsTo, hasOne)*\n\nPrevents joining a foreign table when fetching a record.\n\n### foreignName\n\n*string*\n\n*(available for belongsTo, hasOne)*\n\nA field to be used as a name of a foreign record. Needed when a foreign entity type does not have the field *name*.\n\n### audited\n\n*boolean*\n\n*(available for hasMany)*\n\nLinking and unlinking will be logged in the Stream.\n\n### auditView\n\n*string*\n\n*As of v9.2.3.*\n\nA view used for audit. If not specified, the ordinary view is used.\n\n### readOnly\n\n*boolean*\n\nRead-only links cannot be edited via link and unlink requests. Not possible to relate or unrelate records via the relationship panel. Read-only links can still be edited via the link and link-multiple fields.\n\n### layoutRelationshipsDisabled\n\n*boolean*\n\n*(available for hasMany)*\n\nMakes the link not available in the Bottom Panels layout (in the Layout Manager tool).\n\n### relationName\n\n*string*\n\n*(available for hasMany)*\n\nA relationship name. Defines how a middle table will be named (for a many-to-many relationships).\n\n### additionalColumns\n\n*Object*\n\n*(available for hasMany)*\n\nAdditional columns to be created in a middle table (for a many-to-many relationships).\n\nExample:\n\n```json\n{\n    \"additionalColumns\": {\n        \"role\": {\n            \"type\": \"varchar\",\n            \"maxLength\": 64\n        },\n        \"isPrimary\": {\n            \"type\": \"bool\",\n            \"default\": false\n        }\n    }\n}\n```\n\n### conditions\n\n*(available for hasMany)*\n\nWhere-conditions (for a many-to-many relationships). If multiple links share the same relationship name (middle table), conditions must be defined for each link.\n\nExample:\n\n```json\n{\n    \"links\": {\n        \"toEmailAddresses\": {\n            \"type\": \"hasMany\",\n            \"entity\": \"EmailAddress\",\n            \"relationName\": \"emailEmailAddress\",\n            \"conditions\": {\n                \"addressType\": \"to\"\n            },\n            \"additionalColumns\": {\n                \"addressType\": {\n                    \"type\": \"varchar\",\n                    \"len\": \"4\"\n                }\n            }\n        },\n        \"ccEmailAddresses\": {\n            \"type\": \"hasMany\",\n            \"entity\": \"EmailAddress\",\n            \"relationName\": \"emailEmailAddress\",\n            \"conditions\": {\n                \"addressType\": \"cc\"\n            },\n            \"additionalColumns\": {\n                \"addressType\": {\n                    \"type\": \"varchar\",\n                    \"len\": \"4\"\n                }\n            }\n        }\n    }\n}\n```\n\n### indexes\n\n*(available for hasMany)*\n\n*Object.<string, Object\\>*\n\nIndexes for a middle table. Definition is the same as for entity indexes.\n\n### notMergeable\n\n*boolean*\n\n*(available for hasMany, hasChildren)*\n\nDisable merging related records when duplicate records are being merged.\n\n### utility\n\n*boolean*\n\nThe link will be hidden from the user on the UI whenever possible.\n\n### disabled\n\n*boolean*\n\nDisables the link.\n\n### apiSpecDisabled\n\n*boolean*\n\n*As of v9.3.*\n\nDo not print the link in the OpenAPI spec.\n\n### deferredLoad\n\n*(available for belongsTo and belongsToParent)*\n\n*As of v9.0.0.*\n\nWhen getting a related entity from an entity, it will be returned without loaded values. Values will be loaded on accessing. For belongsToParent there's a downside that it can return an entity even if it's deleted.\n\n## collection\n\nCollection parameters.\n\n### orderBy\n\n*string*\n\nThe default order-by field.\n\n### order\n\n*\"asc\"|\"desc\"*\n\nThe default order direction.\n\n### textFilterFields\n\n*string[]*\n\nFields used by the text filter.\n\n### countDisabled\n\n*boolean*\n\nDisable fetching a total records number (on the list view).\n\n### fullTextSearch\n\n*boolean*\n\nEnable full-text search.\n\n### fullTextSearchOrderType\n\n*\"original\"|\"relevance\"|\"combined\"*\n\nHow to order result of full-text search.\n\n\n## indexes\n\nDatabase indexes.\n\nExample:\n\n```json\n{\n\n    \"indexes\": {\n        \"indexName1\": {\n            \"columns\": [\"createdById\", \"dateSent\"]\n        },\n        \"indexName2\": {\n            \"columns\": [\"messageId\"],\n            \"unique\": true\n        }\n    }\n}\n```\n\n### columns\n\n*string[]*\n\nDatabase columns of the index.\n\n### unique\n\n*boolean*\n\nWhether the index is unique.\n\n## optimisticConcurrencyControl\n\n*boolean*\n\nEnables optimistic concurrency control for the entity type.\n\n## skipRebuild\n\n*boolean*\n\nTo skip database table creation for the entity type.\n\n## hooksDisabled\n\n*boolean*\n\n*As of v8.2.*\n\nDisable hooks.\n\n## transactionalSave\n\n*boolean*\n\n*As of v10.0.*\n\nEnables wrapping record saves and removals into DB transactions.\n\n## repositoryClassName\n\n*class-string<Espo\\ORM\\Repository\\Repository\\>*\n\n*As of v8.2.*\n\nA repository.\n\n## entityClassName\n\n*class-string<Espo\\ORM\\Entity\\>*\n\n*As of v8.2.*\n\nAn entity. Usually should extend `Espo\\Core\\ORM\\Entity`.\n\n## noDeletedAttribute\n\n*boolean*\n\nDisables soft-deletes.\n\n## deleteId\n\n*boolean*\n\n*As of v8.4.*\n\nAdds an additional *deleteId* field that will be written with an random ID when a record is soft-deleted. Useful when need a unique index. Add *deleteId* column to the index.\n"
  },
  {
    "path": "docs/development/metadata/fields.md",
    "content": "# fields\n\nPath: metadata > fields > {fieldType}.\n\nDefinitions for field types.\n\n## notMergeable\n\n*boolean*\n\nWhether this field type is mergeable (when merging duplicate records).\n\n## notCreatable\n\n*boolean*\n\nWhether the field of this type can be created in the Entity Manager tool.\n\n## readOnly\n\n*boolean*\n\nIs this field type Read Only (can't be edited).\n \n## skipOrmDefs\n\n*boolean*\n\nSkip converting to defs for the ORM.\n\n## filter\n\n*boolean*\n\nRecords can be filtered by this field (available as filter on the list view). \n\n## view\n\n*string*\n\nBy default, when displaying a field, the system tries to read the view `\"views/fields/{field-type}\"` (path is `client/src/views/fields/{field-name}.js`). You can define a custom view with this parameter.\n\n## params\n\nArray of field parameters. Theses parameters then can be edited for every field of this field type in the Entity Manager tool.\n\n### Example\n\n```json\n{\n    \"params\": [\n            [\n                \"name\": \"required\",\n                \"type\": \"bool\",\n                \"default\": false\n            ],\n            [\n                \"name\": \"translation\",\n                \"type\": \"varchar\",\n                \"hidden\": true\n            ],\n            [\n                \"name\": \"audited\",\n                \"type\": \"bool\"\n            ],\n            [\n                \"name\": \"readOnly\",\n                \"type\": \"bool\"\n            ]\n        ]  \n}\n```\n\nParameters are passed to the field view in the `params` option.\n\n## fieldDefs\n\nAn object of field type definition. The most of them is used as database column parameter:\n\n- *type* – _\"varchar\"_, _\"int\"_, _\"bool\"_, _\"text\"_, _\"float\"_ etc.;\n- *notNull* – value can't be set as NULL (_true_ | _false_);\n- *unique* – value is unique in the table column (_true_ | _false_);\n- *autoincrement* - value is autoincrement an is calculated with database (_true_ | _false_).\n\nSome other parameters:\n\n- *notStorable* – the column of field with this field type wont be created in the database (_true_ | _false_);\n- *readOnly* – field is not editable (_true_ | _false_);\n- *layoutListDisabled* – field can not be displayed on the list view (_true_ | _false_).\n\n## translatedOptions\n\n*boolean*\n\nDoes the field have options that can be translated.\n\n## hookClassName\n\nCalled after the field is created or edited in the Entity Manager tool.\n\nAvailable methods:\n\n- onRead\n- beforeSave\n- afterSave\n- beforeRemove\n- afterRemove\n\n#### Example\n\n```\n\"hookClassName\": \"Espo\\\\Core\\\\Utils\\\\FieldManager\\\\Hooks\\\\NumberType\"\n```\n\n## fields\n\nDefinitions of additional fields that will be created with this field. E.g. for address field, separate fields (street, city, etc.) are created.\n\n\n## naming\n\n_\"suffix\"_ | _\"prefix\"_ (\"suffix\" is default)\n\nThe naming determines how additional fields will be named.\n\n#### Example\n\nField name: *billingAddress*.\nAdditional field: *country*.\nThe result (with default _suffix_ naming): *billingAddressCountry*.\n\n## actualFields\n\n*string[]*\n\nThe list of actual attributes (which contain useful data). \n\nFor example, for field type `link` in `actualFields` is `['id']`, in `notActualFields` is `['name']`.\nMeans, if you load record with link field, you have values in `{fieldName}Id` and `{fieldName}Name` (suffix naming). But you need set only `{fieldName}Id`, if you want to update this field.\n\nAttributes for field are created by the ORM Converter framework.\n\n## notActualFields\n\n*string[]*\n\nThe list of not actual attributes.\n\n## personalData\n\n*boolean*\n\nWhere the field may contain personal data.\n\n## textFilter\n\n*boolean*\n\nThe field will be available in the list of text filters (in the Entity Manager tool).\n\n## textFilterForeign\n\n*boolean*\n\nThe field will be available in the list of text filters as a foreign field.\n\n## linkDefs\n\n*Object*\n\nIf defined, a link with the same name as the field name will be created. Defines link parameters.\n\n## fullTextSearch\n\n*boolean*\n\nFull-text search will be available for the field.\n\n## fullTextSearchColumnList\n\n*string[]*\n\nColumns used in full-text search.\n\n## valueFactoryClassName\n\n*class-string<Espo\\ORM\\Value\\ValueFactory\\>*\n\nA factory that creates value-objects for this field. A value-object can be obtained by calling `getValueObject` method on an `Entity`.\n\n## attributeExtractorClassName\n\n*class-string<Espo\\ORM\\Value\\AttributeExtractor\\>*\n\nA class that extracts values (attribute => value map) from a value-object. Used internally for obtaining values from a value-object and writing them to an entity.\n\n## validationList\n\n*string[]*\n\nValidations applied server-side.\n\n## mandatoryValidationList\n\n*string[]*\n\nMandatory validations applied server-side. The difference from regular validations is that mandatory are applied always, regardless a corresponding field parameter. E.g. if a field has a parameter *required = false*, then the validation *required* won't be applied unless it's listed as mandatory.\n\n\n## validatorClassNameMap\n\n*Object.<string, class-string<Espo\\Core\\FieldValidation\\Validator\\>\\>*\n\n*As of v7.3.*\n\nValidators defined as validation-type => class-name map.\n\nExample:\n\n```json\n{\n    \"validatorClassNameMap\": {\n        \"required\": \"Espo\\\\Modules\\\\MyModule\\\\Classes\\\\FieldValidators\\\\MyField\\\\RequiredValidator\"\n    }\n}\n```\n\n## validatorClassName\n\nA validator class name. The class should contain validation method corresponding to validations listed in *validationList* and *mandatoryValidationList*. This is a legacy, consider using *validatorClassNameMap*. If not defined, then a class `Espo\\Classes\\FieldValidations\\{Type}Type` is used.\n\n## duplicatorClassName\n\n*class-string<Espo\\Core\\Record\\Duplicator\\FieldDuplicator\\>*\n\nDuplicates attributes of a field. Some fields can require some processing when an entity is being duplicated.\n\n## converterClassName\n\n*class-string<Espo\\Core\\Utils\\Database\\Orm\\FieldConverter\\>*\n\n*As of v7.4.*\n\nConverts field metadata to ORM metadata. Not applied if *fieldDefs* is specified.\n\n## sanitizerClassName\n\n*class-string<Espo\\Core\\FieldSanitize\\Sanitizer\\>*\n\n*As of v8.1.*\n\nAn input sanitizer.\n\n## sanitizerClassNameList\n\n*class-string<Espo\\Core\\FieldSanitize\\Sanitizer\\>[]*\n\n*As of v8.2.*\n\nInput sanitizers.\n\n## massUpdateActionList\n\n*string[]*\n\nActions for mass update.\n"
  },
  {
    "path": "docs/development/metadata/integrations.md",
    "content": "# integrations\n\nPath: metadata > integrations > {IntegrationName}.\n\nIntegration definitions.\n\n## fields\n\n*Object.<string, Object\\>*\n\nField definitions for the integration (to be available at Administration > Integrations).\n\nExample:\n\n```json\n{\n    \"fields\": {\n        \"clientId\": {\n            \"type\": \"varchar\",\n            \"maxLength\": 255,\n            \"required\": true\n        },\n        \"clientSecret\": {\n            \"type\": \"varchar\",\n            \"maxLength\": 255,\n            \"required\": true\n        },\n        \"tenant\": {\n            \"type\": \"enum\",\n            \"options\": [\"common\", \"organizations\", \"consumers\"],\n            \"tooltip\": \"myIntegrationTenant\"\n        }\n    },\n}\n```\n\nA label can be also specified with the *labelTranslation* parameter as of v9.2.\n\n## allowUserAccounts\n\n*boolean*\n\nWhether the integration supposes that users have their own accounts (at User > External Accounts).\n\n## userAccountAclScope\n\n*?string*\n\nA scope name, a user should have access to to be able to use the integration.\n\n## view\n\n*string*\n\nA front-end view for the integration page (at Administration > Integrations).\n\n## userView\n\n*string*\n\nA front-end view for the external account page (at User > External Accounts).\n\n## params\n\n*Object*\n\nDefine any params needed for the integration.\n\n## externalAccountSecretAttributeList\n\n*string[]*\n\nExternal account attributes to be hidden from the front-end.\n"
  },
  {
    "path": "docs/development/metadata/logic-defs.md",
    "content": "# logicDefs\n\nPath: metadata > logicDefs > {Scope}\n\n[Dynamic logic](../../administration/dynamic-logic.md) definitions for an entity type.\n\n*As of v9.1.*\n\n*Before v9.1, it was defined in clientDefs.*\n\nExample:\n\n```json\n{\n    \"fields\": {\n        \"fieldName\": {\n            \"visible\": {\n                \"conditionGroup\": []\n            },\n            \"required\": {\n                \"conditionGroup\": []\n            },\n            \"readOnly\": {\n                \"conditionGroup\": []\n            },\n            \"readOnlySaved\": {\n                \"conditionGroup\": []\n            }\n            \"invalid\": {\n                \"conditionGroup\": []\n            }\n        }\n    },\n    \"panels\": {\n        \"panelName\": {\n            \"visible\": {\n                \"conditionGroup\": []\n            }\n        }\n    },\n    \"options\": {\n        \"fieldName\": [\n            {\n                \"optionList\": [\n                    \"Value 1\",\n                    \"Value 2\"\n                ],\n                \"conditionGroup\": []\n            },\n            {\n                \"optionList\": [\n                    \"Value 3\",\n                    \"Value 4\"\n                ],\n                \"conditionGroup\": []\n            }\n        ]\n    }\n}\n```\n\n## fields\n\n## panels\n\n## options\n\n## cascadingFields\n"
  },
  {
    "path": "docs/development/metadata/notification-defs.md",
    "content": "# notificationDefs\n\nPath: metadata > notificationDefs > {EntityType}.\n\n## assignmentNotificatorClassName\n\n*class-string*\n\nAn assignment notificator. Should implement `Espo\\Core\\Notification\\AssignmentNotificator` interface. Processes assignment notifications. \nCalled after entity is saved.  By default, `Espo\\Core\\Notification\\DefaultAssignmentNotificator` is used.\n\n## emailNotificationHandlerClassNameMap\n\n*Object.<string, class-string\\>*\n\nEmail notification handlers. Should implement `Espo\\Core\\Notification\\EmailNotificationHandler` interface. \nHandles a notification emails (supposed for adding CC, BCC addresses). Provides sender parameters for notification emails (e.g. setting Reply-To address).\n\nExample:\n\n```json\n{\n    \"emailNotificationHandlerClassNameMap\": {\n        \"notePost\": \"Espo\\\\Modules\\\\Crm\\\\Classes\\\\EmailNotificationHandlers\\\\CaseObj\"\n    }\n}\n\n```\n\n## forceAssignmentNotificator\n\n*boolean*\n\nTo force processing assignment notifications (upon record save). Otherwise, it may be bypassed in some scenarios (e.g. when the Stream is enabled \nfor the entity type).\n\n"
  },
  {
    "path": "docs/development/metadata/pdf-defs.md",
    "content": "# pdfDefs\n\nPath: metadata > pdfDefs > {EntityType}.\n\n## dataLoaderClassNameList\n\n*class-string<Espo\\Tools\\Pdf\\DataLoader\\>[]*\n\nList of classes that loads additional data for PDF. Classes should implement the interface `Espo\\Tools\\Pdf\\DataLoader`. Use `__APPEND__` for extending.\n\n## pdfA\n\n*boolean*\n\n*As of v9.2.*\n\nEnables PDF/A.\n\n## attachmentProviderClassNameList\n\n*class-string<Espo\\Tools\\Pdf\\AttachmentProvider\\>[]*\n\n*As of v9.2.*\n\nAttachment providers. PDF/A has to be enabled to be able to include files in PDF.\n"
  },
  {
    "path": "docs/development/metadata/record-defs.md",
    "content": "# recordDefs\n\nPath: metadata > recordDefs > {EntityType}\n\n## duplicateWhereBuilderClassName\n\nA class for building a where clause for duplicate checking.\n\nMust implement `Espo\\Core\\Duplicate\\WhereBuilder` interface.\n\n## defaultsPopulatorClassName\n\n*class-string<Espo\\Core\\Record\\Defaults\\Populator\\>*\n\n*As of v8.2.*\n\nPopulates default values when creating a record.\n\nIs called after the entity is set with input payload values. Usually, it's reasonable to call the default implementation `Espo\\Core\\Record\\Defaults\\DefaultPopulator`.\n\n## readLoaderClassNameList\n\nArray of classes to load additional fields for an entity.\n\nMust implement `Espo\\Core\\FieldProcessing\\Loader` interface.\n\n**Important**: Need to have `\"__APPEND__\"` item in the beginning of the array when extending.\n\n## listLoaderClassNameList\n\nArray of classes to load additional fields for an entity for the list view.\n\nMust implement `Espo\\Core\\FieldProcessing\\Loader` interface.\n\n**Important**: Need to have `\"__APPEND__\"` item in the beginning of the array when extending.\n\n## saverClassNameList\n\nArray of classes to save additional fields.\n\nMust implement `Espo\\Core\\FieldProcessing\\Saver` interface.\n\n!!! note\n\n    Savers are applied on the ORM level (in a hook), not on the Record Service level. Technically, they do not belong to the *recordDefs*, but they are kept here for backward compatibility.\n\n## selectApplierClassNameList\n\nArray of classes for additional handling of a select query. Use for joining additional fields. Do not use for access control logic.\n\nMust implement `Espo\\Core\\Select\\Applier\\AdditionalApplier` interface.\n\n\n## loadAdditionalFieldsAfterUpdate\n\n*boolean*\n\n*As of v8.0.*\n\nLoad additional fields after update. Needed for cases when additional fields need to be re-loaded since they are not actual after update.\n\n## actions\n\nParameters of actions (applied only for the back-end).\n\nParameters:\n\n* disabled – disables the action;\n* allowed – allows the action for non-object scopes;\n* implementationClassName – a class name, should implement `Espo\\Core\\Action\\Action`.\n\n## massActions\n\nParameters of mass actions (applied only for the back-end).\n\nExample:\n\n```json\n{\n    \"massActions\": {\n        \"delete\": {\n            \"allowed\": true\n        }\n    }\n}\n```\n\nParameters:\n\n* disabled – disables the action;\n* allowed – allows the action for non-object scopes;\n* implementationClassName – a class name, should implement `Espo\\Core\\MassAction\\MassAction`.\n\n## actionsDisabled\n\n*bool*\n\nDisable actions in the back-end.\n\n## massActionsDisabled\n\n*bool*\n\nDisable mass actions in the back-end.\n\n## exportDisabled\n\n*bool*\n\nTo disable export regardless ACL.\n\n## actionHistoryDisabled\n\n*bool*\n\n*As of v8.2.*\n\nDisable Action History processing.\n\n## updateDuplicateCheck\n\n*bool*\n\nA boolean parameter. If true, then duplicate checking will be processed while updating a record. By default, it's processed only when creating a new record.\n\n## forceSelectAllAttributes\n\n*bool*\n\n*As of v8.2.*\n\nTo select all attributes when calling find.\n\n## mandatoryAttributeList\n\n*string[]*\n\n*As of v8.2.*\n\nAttributes to select when calling find.\n\n## duplicateLinkList\n\n*string[]*\n\n*As of v8.2.*\n\nLinks to be copied when duplicating a record. As of v8.2.\n\n## relationships\n\n*As of v7.3.*\n\nRelationship parameters. Key-object pairs, where keys are link names.\n\nExample:\n\n```json\n{\n    \"relationships\": {\n        \"cases\": {\n            \"linkRequiredAccess\": \"edit\",\n            \"linkRequiredForeignAccess\": \"read\",\n            \"linkForeignAccessCheckDisabled\": false\n            \"mandatoryAttributeList\": [\"number\"]\n        }\n    }\n}\n```\n\nParameters:\n\n* selectAccessControlDisabled – disable access control when listing related records; only access to a parent record will be checked; as of v8.0;\n* linkRequiredAccess – access to a current record that is needed to be able to link and unlink records (`create`, `read`, `edit`, `delete`, `stream`); applied only in the back-end, for the front-end specify clientDefs > {EntityType} > relationshipPanels > {link} > selectRequiredAccess (*edit* by default);\n* linkRequiredForeignAccess – access to a foreign record that is needed to be able to link and unlink (*edit* by default);\n* linkForeignAccessCheckDisabled – disable foreign record access check when linking; as of v7.4;\n* linkCheckDisabled – disable a link-check functionality linking when through link-multiple field; as of v7.4.4;\n* mandatoryAttributeList – *string[]* – mandatory attributes to be selected when find related; as of v8.2;\n* countDisabled – bool – disable total count; as of 8.2;\n* massLink – bool – allows mass linking; as of 8.2;\n* linkOnlyNotLinked – bool – allow linking only if a record is not linked with any;  as of 8.3;\n\n## createInputFilterClassNameList\n\n*class-string<Espo\\Core\\Record\\Input\\Filter\\>[]*\n\n*As of v8.2.*\n\nCreate input filters.\n\n## updateInputFilterClassNameList\n\n*class-string<Espo\\Core\\Record\\Input\\Filter\\>[]*\n\n*As of v8.2.*\n\nUpdate input filters.\n\n## outputFilterClassNameList\n\n*class-string<Espo\\Core\\Record\\Output\\Filter\\>[]*\n\n*As of v8.2.*\n\nOutput filters.\n\n## beforeReadHookClassNameList\n\nAn array of hooks (applied for API calls). Should implement the `Espo\\Core\\Record\\Hook\\ReadHook` interface.\n\n## earlyBeforeCreateHookClassNameList\n\n*As of v9.0.*\n\nAn array of hooks. Applied for API calls, before validation. Should implement `Espo\\Core\\Record\\Hook\\CreateHook` or `Espo\\Core\\Record\\Hook\\SaveHook` interface.\n\n## beforeCreateHookClassNameList\n\nAn array of hooks (applied for API calls). Should implement the `Espo\\Core\\Record\\Hook\\CreateHook` interface. As of v8.1, can also implement `Espo\\Core\\Record\\Hook\\SaveHook`.\n\n## afterCreateHookClassNameList\n\n*As of v8.2.*\n\nAn array of hooks (applied for API calls). Should implement the `Espo\\Core\\Record\\Hook\\CreateHook` or `Espo\\Core\\Record\\Hook\\SaveHook`.\n\n## earlyBeforeUpdateHookClassNameList\n\n*As of v9.0.*\n\nAn array of hooks. Applied for API calls, before validation. Should implement `Espo\\Core\\Record\\Hook\\UpdateHook` or `Espo\\Core\\Record\\Hook\\SaveHook` interface.\n\n## beforeUpdateHookClassNameList\n\nAn array of hooks (applied for API calls). Should implement the `Espo\\Core\\Record\\Hook\\UpdateHook` interface. As of v8.1, can also implement `Espo\\Core\\Record\\Hook\\SaveHook`.\n\n## afterUpdateHookClassNameList\n\n*As of v8.2.*\n\nAn array of hooks (applied for API calls). Should implement the `Espo\\Core\\Record\\Hook\\UpdateHook` or `Espo\\Core\\Record\\Hook\\SaveHook`.\n\n## beforeDeleteHookClassNameList\n\nAn array of hooks (applied for API calls). Should implement the `Espo\\Core\\Record\\Hook\\DeleteHook` interface.\n\n## afterDeleteHookClassNameList\n\n*As of v8.2.*\n\nAn array of hooks (applied for API calls). Should implement the `Espo\\Core\\Record\\Hook\\DeleteHook` interface.\n\n## beforeLinkHookClassNameList\n\nAn array of hooks (applied for API calls).  Should implement the `Espo\\Core\\Record\\Hook\\LinkHook` interface.\n\n## beforeUnlinkHookClassNameList\n\nAn array of hooks (applied for API calls). Should implement the `Espo\\Core\\Record\\Hook\\UnlinkHook` interface.\n\n## afterLinkHookClassNameList\n\n*As of v8.2.*\n\nAn array of hooks (applied for API calls).  Should implement the `Espo\\Core\\Record\\Hook\\LinkHook` interface.\n\n## afterUnlinkHookClassNameList\n\n*As of v8.2.*\n\nAn array of hooks (applied for API calls). Should implement the `Espo\\Core\\Record\\Hook\\UnlinkHook` interface.\n\n## deletedRestorerClassName\n\n*class-string<Espo\\Core\\Record\\Deleted\\Restorer\\>*\n\n*As of v9.2.*\n\nA deleted record restorer.\n"
  },
  {
    "path": "docs/development/metadata/scopes.md",
    "content": "# scopes\n\nPath: metadata > scopes > {ScopeName}.\n\nСontains scope definitions.\n\n## entity\n\n*boolean*\n\nWhether the scope represents an entity type.\n\n## object\n\n*boolean*\n\nWhether the entity is a business object. Means that it's not an entity for internal system purpose; an object entity represents some business entity.\n\n## module\n\n*string*\n\nThe the name of the module, where this scope is defined. Must be set if the entity type is defined in a module.\n\n## stream\n\n*boolean*\n\nWhether the entity has the stream.\n\n## importable\n\n*boolean*\n\nWhether the entity is available in the Import tool.\n\n## layouts\n\n*boolean*\n\nWhether the entity is available in the Layout Manager tool.\n\n## tab\n\n*boolean*\n\nWhether the scope is available as a navbar tab.\n\n## tabPortal\n\n*boolean*\n\n*As of v9.3.*\n\nTo allow the navbar tab for the portal even if *aclPortal* is false.\n\n## tabAclPermission\n\n*?string*\n\nA permission level required for a user to have the scope available as a navbar tab. Examples: `portal`, `massUpdate`.\n\n## type\n\n*?string*\n\nA template type of the entity.\n\nAvailable values: Base, BasePlus, Person, Company, CategoryTree, Event.\n\n## acl\n\n*boolean|\"boolean\"*\n\nWhether the scope is available in Roles. Available values: true, false, \"boolean\". Boolean means that it will be available in roles w/o actions.\n\n## aclActionList\n\n*string[]*\n\nA list of available actions in Roles. Available item values: create, read, edit, delete, stream.\n\n## aclLevelList\n\n*string[]*\n\nA list of available levels in Roles. Available item values: all, team, own, no.\n\n## aclActionLevelListMap\n\nLists of available levels for specific actions in Roles.\n\nExample:\n\n```json\n\"aclActionLevelListMap\": {\n    \"edit\": [\"own\", \"no\"]\n}\n```\n\n## aclPortal\n\n*boolean|\"boolean\"*\n\nWhether the scope is available in Portal Roles. Available values: true, false, \"boolean\". Boolean means that it will be available in roles w/o actions.\n\n## aclPortalActionList\n\n*string[]*\n\nA list of available actions in Portal Roles. Available item values: create, read, edit, delete, stream.\n      \n## aclPortalLevelList\n\n*string[]*\n\nA list of available levels in Portal Roles. Available item values: all, account, contact, own, no.\n\n## aclPortalActionLevelListMap\n\nLists of available levels for specific actions in Portal Roles.\n\nExample:\n\n```json\n\"aclPortalActionLevelListMap\": {\n    \"edit\": [\"own\", \"no\"]\n}\n```\n\n## aclFieldLevelDisabled\n\n*boolean*\n\n*As of v8.2.*\n\nDisable field level security.\n\n## aclPortalFieldLevelDisabled\n\n*boolean*\n\n*As of v8.2.*\n\nDisable field level security for portals.\n\n## statusField\n \n*string*\n\nDefines a field that should be used as a status field.\n\n## statusFieldLocked\n\n*bool*\n\n*As of v7.5.*\n\nDisables the ability to change the status field.\n\n## disabled\n\n*boolean*\n\nDisables the scope in the system.\n\n## customizable\n\n*boolean*\n\nWhether the entity can be customized in the Entity Manager tool.\n\n## isCustom\n\n*boolean*\n\nEntities created in the Entity Manager tool marked as custom.\n\n## notifications\n\n*boolean*\n\nWhether notifications can be enabled for the entity.\n\n## calendar\n\n*boolean*\n\nWhether the entity can be displayed on the Calendar.\n\n## activity\n\nWhether the entity can be displayed on the Activities panel.\n\n## activityStatusList\n\n*string[]*\n\nStatus values that determine that a record should be shown in the Activities panel.\n      \n## historyStatusList\n\n*string[]*\n\nStatus values that determine that a record should be shown in the History panel.\n\n## calendarOneDay\n\n*boolean*\n\n*As of v9.2.*\n\nDisplay as one-day events in the calendar. Applicable only if the *calendar* parameter is enabled.\n\n## languageIsGlobal\n\n*boolean*\n\nLanguage labels will be available for all users (not restricted by ACL).\n\n## languageAclDisabled\n\n*boolean*\n\nDisables access control application for language labels. All labels of the scope will be available in the front-end regardless of user roles.\n\n## kanbanStatusIgnoreList\n\n*string[]*\n\nStatus values to be ignored on the Kanban view.\n\n## kanbanOrderDisabled\n\n*boolean*\n\nDisable the ability to order items for users.\n\n## hasPersonalData\n\n*boolean*\n\nWhether the entity may contain personal data.\n\n## preserveAuditLog\n\n*boolean*\n\n*As of v9.0.*\n\nDisables audit log cleanup. \n\n## exportFormatList\n\n*string[]*\n\nA list of allowed export formats.\n\nExample:\n\n```json\n{\n    \"exportFormatList\": [\"csv\"]\n}\n```\n\n## currencyConversionAccessRequiredFieldList\n\n*string[]*\n\n*As of v7.5.*\n\nWhen a user converts currency of an entity, edit access to all listed fields is checked. Otherwise, the operation will be forbidden.\n\n## lastViewed\n\nForce to be available in Last Viewed.\n\n"
  },
  {
    "path": "docs/development/metadata/select-defs.md",
    "content": "# selectDefs\n\nPath: metadata > selectDefs > {EntityType}.\n\nParameters used by the [Select](../select-builder.md) framework. This framework converts [search parameters](../api-search-params.md) (from the front-end or API) into ORM-compatible queries.\n\n## accessControlFilterClassNameMap\n\nClass names for access control filters. Classes should implement `Espo\\Core\\Select\\AccessControl\\Filter` interface.\n\nDefault filters are available at `Espo\\Core\\Select\\AccessControl\\Filters`.\n\nThe `mandatory` filter is applied for all users. Use it if you need to apply some access restrictions for all users (including admin).\n\nExample:\n\n```json\n{\n    \"accessControlFilterClassNameMap\": {\n        \"onlyOwn\": \"Espo\\\\Custom\\\\Classes\\\\Select\\\\MyEntityType\\\\AccessControlFilters\\\\OnlyOwn\",\n        \"mandatory\": \"Espo\\\\Custom\\\\Classes\\\\Select\\\\MyEntityType\\\\AccessControlFilters\\\\Mandatory\"\n    }\n}\n```\n\nAvailable out-of-the-box filters:\n\n* mandatory\n* all\n* onlyTeam\n* onlyOwn\n* portalAll\n* portalOnlyAccount\n* portalOnlyContact\n* portalOnlyOwn\n\n## boolFilterClassNameMap\n\nClass names for bool filters. Classes should implement `Espo\\Core\\Select\\Bool\\Filter` interface.\n\n## primaryFilterClassNameMap\n\nClass names for primary filters. Classes should implement `Espo\\Core\\Select\\Primary\\Filter` interface.\n\nExample:\n\n```json\n{\n    \"primaryFilterClassNameMap\": {\n        \"myCustomFilter\": \"Espo\\\\Custom\\\\Classes\\\\Select\\\\MyEntityType\\\\PrimaryFilters\\\\MyCustomFilter\"\n    }\n}\n```\n\n## selectAttributesDependencyMap\n\nWhen the system asking to select a specific attribute, this mapping will force the framework to also select some other fields along with the requested field.\n\nExample:\n\n```json\n{\n    \"selectAttributesDependencyMap\": {\n        \"subject\": [\"name\"],\n        \"personStringData\": [\"fromString\", \"fromEmailAddressId\"],\n        \"id\": [\"order\"]\n    }\n}\n```\n\nIn the example, when the *subject* attribute is requested, the *name* attribute will be selected. We can have the *subject* field on the list layout but don't have the *name* field. Without this mapping the *name* field won't be fetched when we fetch a collection for the list view.\n\nMap to the *id* attribute to make specific attributes to be always selected. This works as the *id* attribute is always requested.\n\n## whereItemConverterClassNameMap\n\nImplementations for custom where items.\n\nExample: \n\n```json\n{\n    \"whereItemConverterClassNameMap\": {\n        \"id_isOfType\": \"Espo\\\\Classes\\\\Select\\\\User\\\\Where\\\\ItemConverters\\\\IsOfType\"\n    }\n}\n```\n\nClasses should implement `Espo\\Core\\Select\\Where\\ItemConverter` interface.\n\nMapping keys a formatted as: `{fieldName}_{conditionItemType}`.\n\nThis mapping allows you to define a custom field filtering implementation. The *conditionItemType* is passed in a [where item](../api-search-params.md#where-items) in the *type* parameter.\n\n## accessControlFilterResolverClassName\n\nA resolver is responsible for choosing an access filter to apply to a select query. Should implement `Espo\\Core\\Select\\AccessControl\\FilterResolver` interface.\n\n## portalAccessControlFilterResolverClassName\n\nA filter resolver for portals. Should implement `Espo\\Core\\Select\\AccessControl\\FilterResolver` interface.\n\n## textFilterClassName\n\nA class that processes the text filter search. Should implement `Espo\\Core\\Select\\Text\\Filter` interface. By default, `Espo\\Core\\Select\\Text\\DefaultFilter` is used.\n\n## orderItemConverterClassNameMap\n\nAn order converter converts order parameters (passed from the frontend through the REST API) to an order data acceptable for the ORM. One can implement a custom converter for a specific field. For example, to make an address field be ordered by a city (when the user sorts by the address column, it will order by the city under the hood).\n\nClasses should implement `Espo\\Core\\Select\\Order\\ItemConverter` interface.\n\nExample: \n\n```json\n{\n    \"orderItemConverterClassNameMap\": {\n        \"someFieldName\": \"Espo\\\\Custom\\\\Classes\\\\Select\\\\MyEntityType\\\\Order\\\\ItemConverters\\\\MyConverter\"\n    }\n}\n```\n\n## ordererClassNameMap\n\n*As of v7.1.*\n\nProvides the ability to apply custom order for a specific field.\n\nClasses should implement `Espo\\Core\\Select\\Order\\Orderer` interface.\n\nExample: \n\n```json\n{\n    \"ordererClassNameMap\": {\n        \"someFieldName\": \"Espo\\\\Custom\\\\Classes\\\\Select\\\\MyEntityType\\\\Order\\\\SomeOrderer\"\n    }\n}\n```\n\n## additionalApplierClassNameList\n\n*As of v9.1.*\n\n*class-string<Espo\\Core\\Select\\Applier\\AdditionalApplier\\>[]*\n\nAdditional appliers. Used for additional handling of a select query. They are always applied. The logic inside the applier can apply some filters conditionally.\n\n"
  },
  {
    "path": "docs/development/metadata/stream-defs.md",
    "content": "# streamDefs\n\nPath: metadata > streamDefs > {EntityType}.\n\nExample:\n\n```json\n{\n    \"followingUsersField\": \"users\",\n    \"subscribersCleanup\": {\n        \"enabled\": true,\n        \"dateField\": \"dateStart\",\n        \"statusList\": [\"Held\", \"Not Held\"]\n    }\n}\n```\n\n## followingUsersField\n\n*string*\n\nA field (of a link-multiple type) that store users which should automatically follow a record. If not set, then the *assignedUsers* field is checked for existence and then used. E.g. for the *Meeting*, it's the *users* field.\n\n## subscribersCleanup\n\n*Object*\n\n### enabled\n\n*boolean*\n\nEnables the cleanup of subscribers.\n\n### dateField\n\n*string*\n\nA date (or date-time) field that stores a value after which followers will automatically unfollow a record.\n\n### statusList\n\n*string[]*\n\nA list of statuses records should have to be eligible for the subscribers cleanup. E.g. for the *Meeting*, it's `[\"Held\", \"Not Held\"]`.\n\n## bypassAssignedUserFollow\n\n*boolean*\n\n*As of v10.0.*\n\nAssigned users won't follow the record when they get assigned to it. If enabling, consider also enabling `forceAssignmentNotificator` in notificationDefs – otherwise, the assignee won't receive any notification.\n\n## allowInternalNotes\n\n*boolean*\n\n*As of v10.0.*\n\nAllow internal notes. If true, it will be possible to post internal posts in the stream. Internal posts are not visible in portals.\n"
  },
  {
    "path": "docs/development/metadata.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Metadata\n\nMetadata is intended for storing application data such as fields, relationships, front-end controllers, views, panels, dashlets etc.\n\n[JSON Schema](https://github.com/espocrm/espocrm/tree/master/schema/metadata) provides autocompletion for IDEs. It works in PhpStorm and VSCode with no setup required.\n\nIn this article:\n\n* [Reference](#reference)\n* [Accessing](#accessing)\n* [How it's stored](#how-its-stored)\n* [Extending](#extending)\n\n## Reference\n\n* [scopes](metadata/scopes.md) – general parameters for scopes and entity types\n* [entityDefs](metadata/entity-defs.md) – entity defs (fields, links, indexes)\n* [aclDefs](metadata/acl-defs.md) – access control for scopes and entity types\n* [selectDefs](metadata/select-defs.md) – Select-framework defs for entity types\n* [recordDefs](metadata/record-defs.md) – CRUD-specific defs for entity types\n* [clientDefs](metadata/client-defs.md) – front-end defs for entity types\n* [entityAcl](metadata/entity-acl.md) – access restriction for specific fields and links for entity types\n* [pdfDefs](metadata/pdf-defs.md) – PDF generation defs for entity types\n* [logicDefs](metadata/logic-defs.md) – dynamic logic for entity types\n* [notificationDefs](metadata/notification-defs.md) – notification defs for entity types\n* [streamDefs](metadata/stream-defs.md) – stream defs for entity types\n* [fields](metadata/fields.md) – field types\n* [dashlets](metadata/dashlets.md)\n* [authenticationMethods](metadata/authentication-methods.md) – authentication methods\n* [integrations](metadata/integrations.md)\n* app – application definitions\n  * [acl](metadata/app-acl.md) – access control\n  * [aclPortal](metadata/app-acl-portal.md) – access control for portals\n  * [actions](metadata/app-actions.md) – Action framework\n  * [addressFormats](metadata/app-address-formats.md)\n  * [adminPanel](metadata/app-admin-panel.md) – Administration panel\n  * [api](metadata/app-api.md)\n  * [appParams](metadata/app-app-params.md) – AppParams framework\n  * [authentication](metadata/app-authentication.md)\n  * [authentication2FAMethods](metadata/app-authentication-2fa-methods.md) – 2-factor authentication methods\n  * [cleanup](metadata/app-cleanup.md)\n  * [client](metadata/app-client.md) – front-end client\n  * [clientNavbar](metadata/app-client-navbar.md) – front-end navbar\n  * [clientIcons](metadata/app-client-icons.md)\n  * [clientRecord](metadata/app-client-record.md)\n  * [clientRoutes](metadata/app-client-routes.md) – front-end routes\n  * [complexExpression](metadata/app-complex-expression.md)\n  * [config](metadata/app-config.md)\n  * [consoleCommands](metadata/app-console-commands.md)\n  * [containerServices](metadata/app-container-services.md)\n  * [currency](metadata/app-currency.md)\n  * [currencyConversion](metadata/app-currency-conversion.md)\n  * [databasePlatforms](metadata/app-database-platforms.md)\n  * [dateTime](metadata/app-date-time.md)\n  * [defaultDashboardLayouts](metadata/app-default-dashboard-layouts.md)\n  * [defaultDashboardOptions](metadata/app-default-dashboard-options.md)\n  * [emailTemplate](metadata/app-email-template.md)\n  * [entityManager](metadata/app-entity-manager.md)\n  * [entityManagerParams](metadata/app-entity-manager-params.md)\n  * [entityTemplateList](metadata/app-entity-template-list.md)\n  * [entityTemplates](metadata/app-entity-templates.md)\n  * [export](metadata/app-export.md)\n  * [fieldProcessing](metadata/app-field-processing.md)\n  * [file](metadata/app-file.md)\n  * [fileStorage](metadata/app-file-storage.md)\n  * [formula](metadata/app-formula.md)\n  * [hook](metadata/app-hook.md) – Hook framework\n  * [image](metadata/app-image.md)\n  * [jsLibs](metadata/app-js-libs.md) – JS libs\n  * [language](metadata/app-language.md)\n  * [layouts](metadata/app-layouts.md)\n  * [linkManager](metadata/app-link-manager.md)\n  * [mapProviders](metadata/app-map-providers.md)\n  * [massActions](metadata/app-mass-actions.md)\n  * [metadata](metadata/app-metadata.md)\n  * [orm](metadata/app-orm.md)\n  * [pdfEngines](metadata/app-pdf-engines.md)\n  * [popupNotifications](metadata/app-popup-notifications.md)\n  * [portalContainerServices](metadata/app-portal-container-services.md)\n  * [reactions](metadata/app-reactions.md)\n  * [rebuild](metadata/app-rebuild.md)\n  * [record](metadata/app-record.md)\n  * [recordId](metadata/app-record-id.md)\n  * [regExpPatterns](metadata/app-reg-exp-patterns.md)\n  * [relationships](metadata/app-relationships.md)\n  * [scheduledJobs](metadata/app-scheduled-jobs.md)\n  * [select](metadata/app-select.md)\n  * [smsProviders](metadata/app-sms-providers.md)\n  * [templateHelpers](metadata/app-template-helpers.md)\n  * [templates](metadata/app-templates.md)\n  * [webSocket](metadata/app-web-socket.md)\n\n\n## Accessing\n\n### Backend\n\nThe Metadata instance (of `Espo\\Core\\Utils\\Metadata` class) is available as a [container service](di.md).\n\nPath to a needed parameter is specified with an array or string.\n\n```php\n<?php\n// entityDefs > Account > fields > type\n$value = $metadata->get(['entityDefs', 'Account', 'fields', 'name', 'type']);\n```\nwill return the string value `\"varchar\"`.\n\n```php\n<?php\n$fields = $metadata->get(['entityDefs', 'Account', 'fields']);\n```\nwill return an associative array with definitions of all fields.\n\nPath defined as string:\n\n```php\n<?php\n$metadata->get(\"entityDefs.Account.fields\");\n```\n\n### Frontend\n\nMetadata object (module ID: `metadata`) is accessible from all view objects by method `#getMetadata`. It's also available via [DI](frontend/dependency-injection.md). It works the same way as the backend's one.\n\n```js\nconst fields = this.getMetadata().get(`entityDefs.Account.fields`);\n```\n\n\n## How it's stored\n\nMetadata is stored in JSON files that can be located in different places:\n\n* `application/Espo/Resources/metadata` – core;\n* `application/Espo/Modules/{ModuleName}/Resources/metadata` – internal modules;\n* `custom/Espo/Modules/{ModuleName}/Resources/metadata` – custom modules;\n* `custom/Espo/Custom/Resources/metadata` – instance specific customizations, customizations made via the admin UI are stored here.\n\nWhen you access data by a path `clientDefs.Account.views.edit` the first lexeme `clientDefs` corresponds to a dir name, the second `Account` – to a file name `Account.json`. All the following lexemes correspond to a path in the JSON object.\n\n```json\n{\n    \"views\": {\n        \"edit\": \"crm:views/account/views/edit\" \n    }\n}\n```\n\nAll JSON files from these directories **get merged** recursively into a single file and stored in an application cache. \n\n## Extending\n\nThe primary method of customization in EspoCRM is defining custom metadata. A developer creates custom JSON files in the *custom* directory. These files then merged with core metadata. Since metadata is merged recursively, you can extend JSON objects and arrays.\n\nYou can **append** values to existing arrays by using the `__APPEND__` reserved string value as the first element of the array. This will preserve array values rather than override them.\n\nExample, `custom/Espo/Custom/Resources/metadata/entityDefs/Account.json`:\n\n```json\n{\n    \"fields\": {\n        \"employeeCount\": {\n          \"type\": \"int\"\n        },\n        \"type\": {\n            \"options\": [\n                \"__APPEND__\",\n                \"Dealer\",\n                \"Lawyer\"\n            ]\n        }\n    }\n}\n```\n"
  },
  {
    "path": "docs/development/modal.md",
    "content": "# Modal view (dialog)\n\n## Modal with a form\n\nExample of a modal dialog with a form.\n\nModal view: `client/custom/src/views/modals/my-dialog.js`\n\n```js\ndefine('custom:views/modals/my-dialog', ['views/modal', 'model'], (ModalView, Model) => {\n\n    return class extends ModalView {\n\n        className = 'dialog dialog-record'\n\n        // language=Handlebars\n        templateContent = `\n            <div class=\"record no-side-margin\">{{{record}}}</div>\n        `,\n\n        // If true, clicking on the backdrop will close the dialog.\n        // Can be 'static', true or false.\n        backdrop = true \n\n        setup() {\n            // action buttons\n            this.buttonList = [\n                {\n                    name: 'doSomething', // handler for 'doSomething' action is bellow\n                    text: this.translate('Some Action', 'labels', 'MyScope'), // button label \n                    style: 'danger',\n                    onClick: () => this.actionDoSomething(),\n                },\n                {\n                    name: 'cancel',\n                    label: 'Cancel',\n                },\n            ];\n            \n            const title = this.options.title || ''; // assuming it's passed from our parent view\n\n            this.headerText = title;             \n            // this.headerHtml = this.getHelper().escapeString(title);\n\n            this.formModel = new Model();\n\n            // define fields\n            this.formModel.setDefs({\n                fields: {\n                    'someString': {\n                        type: 'varchar', // field type\n                        view: 'views/fields/varchar', // optional, to define custom view\n                        required: true, // field param\n                    },\n                    'someCheckbox': {\n                        type: 'bool',\n                    },\n                }\n            });\n\n            this.createView('record', 'views/record/edit-for-modal', {\n                model: this.formModel,\n                selector: '.record',                \n                detailLayout: [ // form layout\n                    {\n                        rows: [\n                            [\n                                {\n                                    name: 'someString',\n                                    labelText: this.translate('someString', 'fields', 'MyScope'),\n                                },\n                                {\n                                    name: 'someCheckbox',\n                                    labelText: this.translate('Some Checkbox', 'labels', 'MyScope'),\n                                },\n                            ],\n                        ],\n                    },\n                ],\n            });\n        }\n\n        async actionDoSomething() {\n            /** @type {import('views/record/edit').default} */\n            const recordView = this.getView('record');\n\n            const isValid = recordView.processFetch();\n\n            if (!isValid) { \n                return;\n            }\n\n            Espo.Ui.notify(' ... ');\n            \n            const response = await Espo.Ajax.postRequest('MyScope/action/doSomething', {\n                id: this.options.id, // passed from the parent view\n                someString: this.formModel.attributes.someString,\n                someCheckbox: this.formModel.attributes.someCheckbox,\n            });\n\n            Espo.Ui.success(this.translate('Done'));\n\n            // We assume that the event 'done' will be caught by the parent view.\n            this.trigger('done', response);\n\n            // Close the modal dialog.\n            this.close();\n        }\n    }\n});\n```\n\nParent view calling our modal view:\n\n```js\nthis.createView('dialog', 'custom:views/modals/my-dialog', {\n    id: this.model.id,\n    title: this.model.get('name'),                \n}, view => {\n    view.render();\n\n    this.listenToOnce(view, 'done', response => {\n        console.log(response);\n    })\n});\n```\n\n## Simple dialog w/o separate view\n\n```js\nthis.createView('dialog', 'views/modal', {\n    templateContent: '<p>{{complexText viewObject.options.message}}</p>',\n    headerText: 'Hello world',\n    backdrop: true,\n    message: 'Some *message*\\n\\nHello world!',\n    buttonList: [\n        {\n            name: 'doSomething',\n            label: this.translate('Do Something'),\n            onClick: () => {\n                // Do something.\n                this.close();\n            },\n            style: 'primary',\n        },\n        {\n            name: 'close',\n            label: this.translate('Close'),\n        }\n    ],\n}, view => {\n    view.render();\n});\n```\n"
  },
  {
    "path": "docs/development/model.md",
    "content": "# Model\n\nA model instance usually represents a single entity record. See the [class](https://github.com/espocrm/espocrm/blob/stable/client/src/model.js).\n\n## Methods\n\n### set\n\nSets an attribute or multiple attributes.\n\n```js\n// Set one attribute.\nmodel.set('attributeName', value);\n\n// Multiple at once.\nmodel.setMultiple({\n    attributeName1: value1,\n    attributeName2: value2,\n});\n\n// With options.\nmodel.setMultiple(attributes, {\n    // suppresses 'change' events\n    silent: true, \n});\n```\n\nYou can pass custom options and check them in 'change' event listeners.\n\n### get\n\nGets an attribute.\n\n```js\nconst value = model.get('attributeName');\n// or model.attributes.attributeName;\n\n// all attributes\nconst attributes = Espo.Utils.cloneDeep(model.attributes);\n```\n\n### save\n\nSaves the model (to the back-end).\n\n```js\n// Assuming model.id is set.\ntry {\n    await model.save()\n} catch() {\n    // Error occurred.\n    return;\n}\n```\n\n### fetch\n\nFetches the model (from the backend). Loads attribute values to the model. Returns a promise.\n\n```js\n// Assuming model.id is set.\nasync model.fetch();\n```\n\n### getClonedAttributes\n\nGet cloned attributes. Returns an object.\n\n```js\nconst attributes = model.getClonedAttributes();\n```\n\n### populateDefaults\n\nPopulate default values.\n\n```js\nmodel.populateDefaults();\n```\n\n### setDefs\n\nSets field and link defs. May be needed if a model instantiated explicitly, not by the factory.\n\n```js\nmodel.setDefs({\n    fields: {},\n    links: {},\n});\n```\n\n## Properties\n\n### id\n\n*string*\n\nA record ID.\n\n### entityType\n\n*string*\n\nAn entity type.\n\n### urlRoot\n\n*string*\n\nA root API URL to use for syncing with the backend. For non-new records, an ID part will be appended.\n\n### url\n\n*string*\n\nAn API URL to use for syncing with the backend. If specified, urlRoot will be omitted.\n\n### attributes\n\n*Record*\n\nAttribute values.\n\n```js\nconst name = model.attributes.name;\n```\n\n## Instantiating\n\nModel-factory is available in views. The model-factory allows you to create a model instance of a specific entity type.\n\n```js\nexport default class extends View {\n\n    setup() {            \n        // Use wait to hold off rendering until model is loaded.     \n        this.wait(this.loadModel());\n    }\n\n    async loadModel() {\n        this.model = await this.getModelFactory().create('Account');\n\n        // entityType is set by the factory.\n        //const entityType = this.model.entityType;\n\n        this.model.id = this.options.id;\n\n        await model.fetch(); \n    }\n}\n```\n\nInstantiating w/o factory:\n\n```js\nimport View from 'view';\nimport Model from 'model';\n\nexport default class extends View {\n\n    setup() {\n        const model = new Model();\n\n        // URL will be used when fetching and saving.\n        model.urlRoot = 'MyModel'; \n        model.id = 'someId';\n        \n        this.wait(\n            // This performs `GET MyModel/someId` API call.\n            model.fetch(); \n        );\n    }\n}\n```\n\n## Events\n\nNote: `listenTo` and `listenToOnce` are methods of the *view* class.\n\n### change\n\nWhen model attributes get changed (not necessarily synced with backend).\n\n```js\nthis.listenTo(model, 'change', (model, options) => {\n    if (this.model.hasChanged('someAttribute')) {\n        // someAttribute is changed\n    }\n    \n    if (options.ui) {\n        // changed via UI\n        // this options is set by field view\n    }\n\n    // The 'action' option indicates how the change originated.\n    // Possible values: fetch, save, ui, cancel-edit.\n    console.log(options.action);\n\n    // If you want to change the same model within this handler,\n    // use setTimeout with a zero delay to avoid a potential loop.\n});\n\nthis.listenToOnce(model, 'change:someAttribute', (model, value, options) => {\n    // someAttribute is changed\n});\n```\n\n### sync\n\nModel synced with backend.\n\n```js\nthis.listenTo(model, 'sync', (model, response, options) => {\n    // Synced with backend – fired after fetch or save.\n\n    // The 'action' option indicates how the sync originated.\n    // Possible values: fetch, save, destroy.\n    console.log(options.action);\n});\n```\n\n### destroy\n\nOnce model is removed (after *DELETE* request).\n\n## Additional events\n\nDefined in the application.\n\n### after:relate\n\nOnce relationship panel updated. Available on the detail view.\n\n### after:relate:{link}\n\nOnce a specific relationship panel updated. Available on the detail view.\n\n### update-all\n\nThis event is not fired. But you can fire it to refresh all relationship panels. Available on the detail view.\n\n### update-related:{link}\n\nFire this event to refresh a specific relationship panel. Available on the detail view.\n\n\n## Other\n\nPassing model to a child view:\n\n```js\nthis.createView('someName', 'custom:views/some-view', {\n    model: this.model,\n});\n```\n\nOr:\n\n```js\nconst view = new MyView({model});\n```\n"
  },
  {
    "path": "docs/development/modules.md",
    "content": "# Modules\n\nThe best practice is to place customizations in a module directory:\n\n* `custom/Espo/Modules/{YourModule}/` – backend (CamelCase name);\n* `client/custom/modules/{your-module}/` – frontend (hyphen name).\n\n## Order\n\nEvery module has its *order* property. The order is used by the system to define which module to load first. For example, if two modules have some metadata with the same key, the metadata of the module that has a higher order will be used. If two modules have the controller classes with the same name, then the class of the module that has a higher order will be used.\n\nThe *order* property is defined in `custom/Espo/Modules/{YourModule}/Resources/module.json`:\n\n```json\n{\n    \"order\": 16\n}\n```\n\nRequires clearing cache after changes.\n\n## Routes\n\nA module can define additional [API routes](api-action.md#routing). They are defined in `custom/Espo/Modules/{YourModule}/Resources/routes.json`.\n\nRequires clearing cache after changes.\n\n## Composer\n\nYou can create a `composer.json` in your module directory to include 3rd party libraries. To let Espo know about these libraries, you need to create an [autoload configuration file](autoload.md) in your module.\n\n## JS modules\n\nWhen referencing ES (or AMD) modules located in an Espo module, use the path: `module/{your-module}/*`. Example: `module/my-module/views/fields/my-field`.\n\nWhen using [ext-template](https://github.com/espocrm/ext-template), the path to your Espo module will be automatically written in *jsconfig.json*. That will allow an IDE to properly locate module files. \n"
  },
  {
    "path": "docs/development/new-function-in-formula.md",
    "content": "# Custom functions for Formula\n\nEspoCRM provides the ability to create custom functions that can be used in formula-script. \n\nCreate a file `custom/Espo/Custom/FormulaFunctions/MyContains.php` with the code:\n\n```php\n<?php\nnamespace Espo\\Custom\\FormulaFunctions;\n\nuse Espo\\Core\\Formula\\Exceptions\\TooFewArguments;\nuse Espo\\Core\\Formula\\Func;\nuse Espo\\Core\\Formula\\EvaluatedArgumentList;\n\nclass MyContains implements Func\n{\n    public function __construct(/* pass needed dependencies */) {}\n\n    public function process(EvaluatedArgumentList $arguments): mixed\n    {\n        if (count($arguments) < 2) {\n            throw TooFewArguments::create(2);\n        }\n\n        $haystack = $arguments[0];\n        $needle = $arguments[1];\n\n        if (count($arguments) > 2) {\n            $offset = $arguments[2];\n            \n            return strpos($haystack, $needle, $offset) !== false;\n        }\n                \n        return strpos($haystack, $needle) !== false;\n    }\n}\n```\n\nCreate a file `custom/Espo/Custom/Resources/metadata/app/formula.json` and add the code:\n\n```json\n{\n    \"functionClassNameMap\": {\n        \"myNamespace\\\\myContains\": \"Espo\\\\Custom\\\\FormulaFunctions\\\\MyContains\"\n    },\n    \"functionList\": [\n        \"__APPEND__\",\n        {\n            \"name\": \"myNamespace\\\\myContains\",\n            \"insertText\": \"myNamespace\\\\myContains(HAYSTACK, NEEDLE, OFFSET)\"\n        }\n    ]\n}\n```\n\nClear cache.\n\n"
  },
  {
    "path": "docs/development/orm-value-objects.md",
    "content": "# Value Objects\n\n*As of v7.0.*\n\n* Value objects are immutable.\n* Value objects contain modification methods that return a cloned instance.\n* Default value objects are available in the namespace `Espo\\Core\\Field`.\n* It's possible to register custom value object for a specific field type or for a specific field.\n\nWhen defining getters and setters in an Entity class, it's recommended to use value objects for such field types:\n\n* date\n* datetime\n* datetimeOptional\n* address\n* currency\n\nAll field types with registered value object:\n\n* date\n* datetime\n* datetimeOptional\n* address\n* currency\n* email\n* phone\n* link\n* linkParent\n* linkMultiple\n\nBaseEntity's methods *getValueObject* and *setValueObject* will work for field types with registered value object.\n\n```php\n<?php\n\n$valueObject = $entity->getValueObject($field);\n$entity->setValueObject($field, $valueObject);\n$entity->setValueObject($field, null);\n```\n\nGetter and setter:\n\n```php\n<?php\nnamespace Espo\\Modules\\MyModule\\Entities;\nuse Espo\\Core\\Field\\Date;\n\nclass MyEntity extends Entity\n{\n    public function getDateDue(): ?Date\n    {\n        // It's also possible to use `getValueObject`.\n\n        $rawValue = $this->get('dateDue');\n\n        if ($rawValue === null) {\n            return null;\n        }\n\n        return Date::fromString($rawValue);\n    }\n\n    public function setDateDue(?Date $dateDue): self\n    {\n        $this->setValueObject('dateDue', $dateDue);\n\n        return $this;\n    }\n}\n\n```\n\n## Supported field types\n\n### Address\n\n```php\n<?php\n\n$address = $accountEntity->getBillingAddress() ?? new Address();\n\n$country = $address->getCountry();\n$city = $address->getCity();\n```\n\n```php\n<?php\n\n$address = Address::create()\n    ->withCity($city)\n    ->withCountry($country)\n    ->withPostalCode($postalCode);\n\n$accountEntity->setBillingAddress($address);\n```\n\n### Currency\n\n```php\n<?php\n\n$value = new Currency($amount, 'USD');\n\n$valueInEur = $converter->convert($value, 'EUR');\n\n$opportunityEntity->setAmount($valueInEur);\n```\n\n### Email address, Phone number\n\n```php\n<?php\n\n$emailAddressGroup = $accountEntity->getEmailAddressGroup();\n\n$primary = $emailAddressGroup->getPrimary();\n\n$modifiedEmailAddressGroup = $emailAddressGroup\n    ->withAddedEmailAddress(\n        EmailAddress::create('address@test.com')->optedOut()\n    );\n\n$accountEntity->setEmailAddressGroup($modifiedEmailAddressGroup);\n```\n\nThe same is available for phone numbers.\n\n### Date, DateTime, DateTimeOptional\n\n```php\n<?php\n\n$closeDate = $opportunityEntity->getCloseDate();\n\n$opportunityEntity->setCloseDate(\n    $closeDate->modify('+1 month')\n);\n```\n\n### Link, Link-Parent, Link-Multiple\n\n```php\n<?php\n$parentLink = LinkParent::create($entityType, $id);\n```\n\n```php\n<?php\n$contact = LinkMultipleItem\n    ::create($contact->getId())\n    ->withColumnValue('role', 'Decision Maker');\n\n$contacts = LinkMultiple::create([$contact->getId()]);\n```\n\n## Registering\n\n!!! note\n\n    Registering own value object types might be excessive as it's possible to manually handle value object creation and consumption in getter and setters of an entity.\n\nRegistering a custom value object type for a specific field type.\n\nFor a field type you need to define 2 parameters in metadata > fields > {fieldType}:\n\n* `valueFactoryClassName` – implementation of `Espo\\ORM\\Value\\ValueFactory` interface;\n* `attributeExtractorClassName` – implementation of `Espo\\ORM\\Value\\AttributeExtractor` interface.\n\nIt's also possible to register a value object for a specific field in metadata > entityDefs > {entityType} > fields > {fieldName}:\n\n* `valueFactoryClassName`;\n* `attributeExtractorClassName`.\n"
  },
  {
    "path": "docs/development/orm.md",
    "content": "# ORM\n\nEspoCRM utilizes own built-in ORM (object-relational mapping). Create, update, read, delete and search operations are performed via the Entity Manager instance.\n\nThe *EntityManager* is available as a [*container service*](di.md). It's a central access point for ORM functionalities.\n\nA *Repository* class serves for fetching and storing records. Base classes: `Espo\\ORM\\Repositories\\RDBRepository`, `Espo\\Core\\Repositories\\Database`. *RDB* stands for a *relational database*.\n\nAn *Entity* class represents a single record. Each [entity type](../administration/terms-and-naming.md#entity-type) has its own entity class. Base class: `Espo\\Core\\ORM\\Entity`, interface: `Espo\\ORM\\Entity`.\n\nAn *EntityCollection* is a collection of entities. It's returned by *find* operations. An *SthCollection* is a collection of entities, consuming much less memory than EntityCollection. Collections are iterable.\n\nThe ORM uses a data-mapper approach. Note that it does not have an identity map – fetching the same record multiple times in a row will return different instances (of the same record).\n\n## See also\n\n* [Complex expressions](../user-guide/complex-expressions.md)\n* [Value objects](orm-value-objects.md)\n* [Custom entity type](custom-entity-type.md)\n* [Entity definitions](metadata/entity-defs.md)\n\n## Injecting Entity Manager\n\nThe Entity Manager is available as a [*Container*](di.md) service.\n\nA class with the `entityManager` dependency:\n\n```php\n<?php\nnamespace Espo\\SomeNamespace;\n\nuse Espo\\ORM\\EntityManager;\n\nclass SomeClass\n{    \n    public function __construct(private EntityManager $entityManager)\n    {}\n}\n```\n\n## Working with entities\n\n### Create new entity\n\n```php\n<?php\n$entity = $entityManager->getNewEntity($entityType);\n```\n\nOr type hinted:\n\n```php\n<?php\nuse Espo\\Modules\\MyModule\\Entities\\MyEntity;\n\n// Will infer a proper MyEntity type. Useful for static analysis and IDEs\n// that support generic types.\n$entity = $entityManager->getRDBRepositoryByClass(MyEntity::class)->getNew();\n```\n\n!!! note\n\n    It creates a new instance but doesn't store it in DB. The entity doesn't have an ID yet.\n\n### Fetch existing entity\n\n```php\n<?php\n$entity = $entityManager->getEntityById($entityType, $id);\n```\n\nOr type hinted:\n\n```php\n<?php\nuse Espo\\Modules\\MyModule\\Entities\\MyEntity;\n\n$entity = $entityManager->getRDBRepositoryByClass(MyEntity::class)->getById($id);\n```\n\n### Store entity\n\n```php\n<?php\n$entityManager->saveEntity($entity);\n```\n\n#### Save options\n\nSave with options:\n\n```php\n<?php\nuse Espo\\Core\\ORM\\Repository\\Option\\SaveOption;\n\n$entityManager->saveEntity($entity, [SaveOption::SILENT => true]);\n```\n\nAvailable options:\n\n* skipAll – skip all additional processing;\n* skipHooks – skip all hooks; workflows, formula will be ignored;\n* silent – workflows will be ignored, modifiedAt and modifiedBy fields won't be changed;\n* skipCreatedBy – createdBy won't be set to the current user;\n* skipModifiedBy – modifiedBy won't be set to the current user;\n* createdById – override createdBy with a passed user ID;\n* modifiedById – override modifiedBy.\n\nOptions in constants available here: `Espo\\Core\\ORM\\Repository\\Option\\SaveOption`.\n\n### Create and store entity\n\nStores the record in DB and returns an entity instance.\n\n```php\n<?php\n$entity = $entityManager->createEntity($entityType, [\n    'name' => 'Test',\n    'status' => 'Hello',\n]);\n```\n\n### Remove entity\n\nSoft-deletes the record.\n\n```php\n<?php\n$entityManager->removeEntity($entity);\n```\n\n### Get attribute value\n\nReturn the value of a given attribute. An attribute usually corresponds to a column in DB.\n\n```php\n<?php\n$attributeValue = $entity->get('attributeName');\n```\n\n!!! note\n\n    As EspoCRM supports custom fields and relationships which are added dynamically without the need to compile, attribute accessor methods *get*, *set* and *has* were introduced. For type safety, consider creating getters and setters for needed attributes in your custom Entity class. Use these methods in your business logic code.\n\n### Has attribute value\n\nChecks whether an attribute is set. Note: If it's set to *null*, it will return *true*. An attribute may not be set if the entity was fetched with only a specified attribute list.\n\n```php\n<?php\n$attributeIsSet = $entity->has('attributeName'); // true or false\n```\n\n### Set attribute value\n\nOne:\n\n```php\n<?php\n$entity->set('attributeName', 'Test Value');\n```\n\nMultiple:\n\n```php\n<?php\n$entity->setMultiple([\n    'name' => 'Test Name',\n    'assignedUserId' => '1',\n]);\n```\n\n### Clear attribute value\n\nThis will unset the attribute. If you save the Entity after that, it will not change the value to NULL in database. Very rarely used. Not recommended.\n\n```php\n<?php\n$entity->clear('attributeName');\n```\n\n### Fetched attributes\n\nCheck whether an attribute was changed.\n\n```php\n<?php\n// a value that was set once the record was fetched from DB\n$value = $entity->getFetched('attributeName');\n\n// check whether an attribute was changed since the last syncing with DB\n$attributeChanged = $entity->isAttributeChanged('attributeName');\n```\n\n### Get all attribute values\n\nReturns all attributes with their values.\n\n```php\n<?php\n// Returns an stdClass instance.\n$valueMap = $entity->getValueMap();\n```\n\n### Delete from DB\n\nDeletes the record permanently.\n\n```php\n<?php\n$entityManager->getRDBRepository($entityType)->deleteFromDb($id);\n```\n\n## Repository\n\nUse ORM's repositories to fetch and save entities. A repository instance is instantiated per entity type.\n\n!!! note\n\n    It may be reasonable to wrap all interactions with the repository in a higher-level class (usually also called a Repository), so that your business-logic classes do not depend directly on the Entity Manager. This improves testability.\n\nGet a repository by an entity class:\n\n```php\n<?php\nuse Espo\\Modules\\Crm\\Entities\\Account;\n\n// Returns `Collection<Account>`.\n$accountRepository = $entityManager->getRDBRepositoryByClass(Account::class);\n```\n\n```php\n<?php\n// The proper type of the returned Entity can be inferred. Useful\n// for static analysis and IDEs that support generic types.\n$account = $entityManager\n    ->getRDBRepositoryByClass(Account::class)\n    ->getById($id);\n```\n\nNote: To be able to fetch the repository by an entity type, your [custom entity](custom-entity-type.md#entity-class) needs to have the *ENTITY_TYPE* constant.\n\nGet a repository by an entity type:\n\n```php\n<?php\n// $entityType can be, for example, 'Opportunity'.\n\n$repository = $entityManager->getRDBRepository($entityType);\n```\n\n### Find\n\n```php\n<?php\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->where([\n        'type' => 'Customer',\n    ])\n    ->find();\n```\n\nDescending order:\n\n```php\n<?php\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->limit(0, 10)\n    ->order('createdAt', 'DESC')\n    ->find();\n```\n\nComplex order:\n\n```php\n<?php\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->order([\n        ['createdAt', 'ASC'],\n        ['name', 'DESC'],\n    ])\n    ->find();\n```\n\nOr:\n\n```php\n<?php\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->order('createdAt', 'ASC')\n    ->order('name', 'DESC')\n    ->find();\n```\n\nOr:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\Part\\Expression as Expr;\n\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->order(\n        Expr::concat(\n            Expr::column('firstName'),\n            Expr::column('lastName')\n        ),\n        'DESC',            \n    )\n    ->find();\n```\n\nOrdering by a value list:\n\n```php\n<?php\n$collection = $entityManager\n    ->getRDBRepository('Opportunity')\n    ->order('LIST:stage:Prospecting,Qualification,Proposal')\n    ->find();\n```\n\nFeeding a query to a repository:\n\n```php\n<?php\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->clone($query)\n    ->limit(0, 10)\n    ->find();\n```\n\nFinding the first one:\n\n```php\n<?php\n$entity = $entityManager\n    ->getRDBRepository($entityType)\n    ->where([\n        'type' => 'Customer',\n    ])\n    ->findOne();\n```\n\nYou can use *getRDBRepositoryByClass* for type safety:\n\n```php\n<?php\nuse Espo\\Modules\\Crm\\Entities\\Account;\n\n$entity = $entityManager\n    ->getRDBRepositoryByClass(Account::class)\n    ->findOne();\n\n// Static analysis infers the entity's type.\n```\n\n### Get new\n\nPrepare a new entity without saving it:\n\n```php\n<?php\nuse Espo\\Modules\\Crm\\Entities\\Account;\n\n$account = $entityManager->getRDBRepositoryByClass(Account::class)\n    ->getNew();\n```\n\n### Save\n\nSave an entity:\n\n```php\n<?php\nuse Espo\\Modules\\Crm\\Entities\\Account;\n\n$entityManager->getRDBRepositoryByClass(Account::class)\n    ->save($account);\n```\n\n### Remove\n\nRemove an entity (soft delete):\n\n```php\n<?php\nuse Espo\\Modules\\Crm\\Entities\\Account;\n\n$entityManager->getRDBRepositoryByClass(Account::class)\n    ->remove($account);\n```\n\n## Relations\n\n!!! note\n\n    As of v8.4, the *getRelation* method is available in the *EntityManager*. `$entityManager->getRelation($entity, 'relationName');` Before, it could be accessed from a repository.\n\n### Find related\n\nHas-Many:\n\n```php\n<?php\n// All.\n$opportunityCollection = $entityManager\n    ->getRelation($account, 'opportunities')\n    ->find();\n\n// Filter.\n$opportunityCollection = $entityManager\n    ->getRelation($account, 'opportunities')\n    ->limit(0, 10)\n    ->where($whereClause)\n    ->find();\n\n// First one.\n$opportunity = $entityManager\n    ->getRelation($account, 'opportunities')\n    ->order('createdAt', 'DESC')\n    ->findOne();\n```\n\nBelongs-To or Has-One:\n\n```php\n<?php\n$account = $entityManager\n    ->getRelation($task, 'account')\n    ->findOne();\n```\n\nFiltering by a relation column:\n\n```php\n<?php\n $leads = $entityManager\n    ->getRelation($targetList, 'leads')\n    ->where(['@relation.optedOut' => false])\n    ->find();\n```\n\n*optedOut* is a column in the middle table.\n\n### Relate entities\n\n```php\n<?php\n$entityManager\n    ->getRelation($account, 'opportunities')\n    ->relate($opportunity);\n\n$entityManager\n    ->getRelation($account, 'opportunities')\n    ->relateById($opportunityId);\n\n// With relationship column setting.\n$entityManager\n    ->getRelation($account, 'contacts')\n    ->relate($contact, ['role' => 'CEO']);\n```\n\n### Unrelate entities\n\n```php\n<?php\n$entityManager\n    ->getRelation($account, 'opportunities')\n    ->unrelate($opportunity);\n\n$entityManager\n    ->getRelation($account, 'opportunities')\n    ->unrelateById($opportunityId);\n```\n\n### Update columns\n\n```php\n<?php\n$entityManager\n    ->getRelation($account, 'contacts')\n    ->updateColumns($contact, ['role' => 'CEO']);\n\n$entityManager\n    ->getRelation($account, 'contacts')\n    ->updateColumnsById($contactId, [\n        'role' => 'CEO', // relationship column\n    ]);\n```\n\n### Check whether related\n\n```php\n<?php\n$isRelated = $entityManager\n    ->getRelation($account, 'opportunities')\n    ->isRelated($opportunity);\n```\n\n### Managing from within Entity class\n\n*As of v9.0.*\n\nA developer can add getter and setters to an Entity class which will allow to read and set related records.\n\nIn a custom entity type class, you can define getter and setters for relationships. If you call the same getter multiple times, it will return the same instance. It's useful when the same related entity is accessed in multiple hooks during save. After save, the map will be reset – the getter won't return the same instance as before save.\n\nGet one:\n\n```php\n<?php\n// Returns an Account entity instance.\n// 'account' is a link name.\npublic function getAccount(): ?Account\n{\n    /** @var ?Account */\n    return $this->relations->getOne('account');\n}\n```\n\nSet one:\n\n```php\n<?php\n// 'account' is a link name.\npublic function setAccount(?Account $account): self\n{\n    return $this->setRelatedLinkOrEntity('account', $account);\n}\n```\n\nGet many:\n\n```php\n<?php\n/**\n * @return Traversable<int, Account>\n */\npublic function getAccounts(): Traversable\n{\n    /** @var Traversable<int, Account> */\n    return $this->relations->getMany('accounts');\n}\n```\n\nNote that setting collections (many-to-many, one-to-many) is not supported. Use *$entityManager->getRelation* or set the *LinkMultiple* value object instead.\n\nUsage:\n\n```php\n<?php\n$entity->setAccount($account);\n\n$account = $entity->getAccount();\n\n// The same instance is returned. Useful to prevent re-fetching in different hooks.\nassert($account === $entity->getAccount());\n\n$em->saveEntity($entity);\n```\n\n\n## Collections\n\nCollections contains Entities. An *EntityCollection* is a regular collection of entities. An *SthCollection* is a collection of entities, consuming much less memory. It's reasonable when working with large query results. It does not allocate memory for all results but only for a current entity (e.g. when iterating).\n\nIteration:\n\n```php\n<?php\nforeach ($collection as $entity) {\n    // Do something with entity.\n}\n```\n\nGet all values:\n\n```php\n<?php\n$valueMapList = $collection->getValueMapList(); // stdClass[]\n```\n\nFactory:\n\n```php\n<?php\n$collection = $entityManager->getCollectionFactory()->create(); // EntityCollection\n$collection[] = $entity;\n\n$sthCollection = $entityManager->getCollectionFactory()->createFromQuery($selectQuery); // SthCollection\n```\n\n## Select Query Parameters\n\n### Where clause\n\n#### Comparison operators\n\nSupported comparison operators: `>`, `<`, `>=`, `<=`, `=`, `!=`.\n\n```php\n<?php\n$opportunityList = $entityManager\n    ->getRDBRepository('Opportunity')\n    ->where([\n        'amount>=' => 100\n    ])\n    ->find();\n```\n\n#### IN and NOT IN operators\n\n```php\n<?php\n$opportunityList = $entityManager\n    ->getRDBRepository('Opportunity')\n    ->where([\n        'stage' => ['Closed Lost', 'Closed Won']\n    ])\n    ->find();\n```\n\n```php\n<?php\n$opportunityList = $entityManager\n    ->getRDBRepository('Opportunity')\n    ->where([\n        'stage!=' => ['Closed Lost', 'Closed Won']\n    ])\n    ->find();\n```\n\n#### LIKE operators\n\nSupported  operators:\n\n* `*` - LIKE\n* `!*` - NOT LIKE\n\n```php\n<?php\n$opportunityList = $entityManager\n    ->getRDBRepository('Opportunity')\n    ->where([\n        'name*' => '%service%',\n    ])\n    ->find();\n```\n\n#### OR, AND operators\n\n```php\n<?php\n$opportunityList = $entityManager\n    ->getRDBRepository('Opportunity')\n    ->where([\n        [\n            'OR' => [\n                ['stage' => 'Closed Won'],\n                ['stage' => 'Closed Lost'],\n            ],\n            'AND' => [\n                'amountConverted>' => 100,\n                'amountConverted<=' => 999,\n            ],\n        ]\n    ])\n    ->findOne();\n```\n\n#### Sub-query\n\n```php\n<?php\nuse Espo\\ORM\\Query\\Part\\Condition as Cond;\n\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->where(\n        Cond::in(Cond::column('id'), $subQuery)\n    )\n    ->find();\n```\n\n#### Condition\n\n*As of v7.0.*\n\n```php\n<?php\nuse Espo\\ORM\\Query\\Part\\Condition as Cond;\n\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->where(\n        Cond::or(\n            Cond::equal(Cond::column('someColumn'), '1'),\n            Cond::equal(Cond::column('someColumn'), '2')\n        )\n    )\n    ->find();\n```\n\n```php\n<?php\nuse Espo\\ORM\\Query\\Part\\Condition as Cond;\n\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->where(\n        Cond::in(Cond::column('id'), $subQuery)\n    )\n    ->find();\n```\n\n### Distinct\n\n```php\n<?php\n$opportunityList = $entityManager\n    ->getRDBRepository('Opportunity')\n    ->distinct()\n    ->find();\n```\n\n### Join\n\nJoin relationship:\n\n```php\n<?php\n$contactList = $entityManager\n    ->getRDBRepository('Contact')\n    ->distinct()\n    ->join('opportunities')\n    ->where([\n        'opportunities.stage' => 'Closed Won'\n    ])\n    ->find();\n```\n\nLeft-Join relationship:\n\n```php\n<?php\n$contactList = $entityManager\n    ->getRDBRepository('Contact')\n    ->distinct()\n    ->leftJoin('opportunities')\n    ->find();\n```\n\n'opportunities' is a relationship name.\n\nJoin alias:\n\n```php\n<?php\n$contactList = $entityManager\n    ->getRDBRepository('Contact')\n    ->distinct()\n    ->join('opportunities', 'aliasForJoinedTable')\n    ->where([\n        'aliasForJoinedTable.stage' => 'Closed Won'\n    ])\n    ->find();\n```\n\nJoining any table (a table name should start with an upper case letter):\n\n```php\n<?php\n$meetingList = $entityManager\n    ->getRDBRepository('Meeting')\n    ->join(\n        'MeetingUser', // meeting_user table\n        'meetingUser', // alias\n        [\n            // Colon indicates that the right part is not a value.\n            // It translates to `meetingUser.meeting_id = meeting.id`.\n            'meetingUser.meetingId:' => 'id', // join condition\n            'meetingUser.deleted' => false, // important\n        ],\n    )\n    ->where([\n        'meetingUser.userId' => $user->getId()\n    ])\n    ->find();\n```\n\nJoining a table with the query builder:\n\n```php\n<?php\n$query = $entityManager\n    ->getRDBRepository('Meeting')\n    ->select([\n        'id',\n        'name',\n        ['meetingUser.status', 'meetingStatus'], // expression and alias\n    ])\n    ->join(\n        'MeetingUser', // meeting_user table\n        'meetingUser', // alias\n        [\n            'meetingUser.meetingId:' => 'id', // join condition\n            'meetingUser.deleted' => false, // important\n        ],\n    )\n    ->where([\n        'meetingUser.userId' => $user->getId(),\n    ])\n    ->find();\n```\n\n!!! important\n\n    When joining by a table name (upper case is used), `'deleted' => false` filter is not applied implicitly. You need to provide it explicitly.\n\n### Group By\n\n```php\n<?php\n$query = $entityManager\n    ->getQueryBuilder()\n    ->select()\n    ->from('Opportunity') // entity type\n    ->select(['MONTH:(closeDate)', 'SUM:(amountConverted)']) // complex expressions\n    ->groupBy('MONTH:(closeDate)') // complex expression\n    ->where([\n        'stage' => 'Closed Won'\n    ])\n    ->order('MONTH:(closeDate)')\n    ->build();\n\n$pdoStatement = $entityManager\n    ->getQueryExecutor()\n    ->execute($query);\n\n$rowList = $pdoStatement->fetchAll(\\PDO::FETCH_ASSOC);\n```\n\n## STH collection\n\nIf STH is set (with `sth` method), the find method will return a collection (instance of `SthCollection`) that doesn't allocate memory for all result data.\n\n```php\n<?php\n$collection = $entityManager\n    ->getRDBRepository('Email')\n    ->limit(0, 10000)\n    ->sth()\n    ->find();\n\nforeach ($collection as $entity) {\n    // memory is allocated for each item, when collection is iterated\n}\n```\n\n## Complex expressions\n\n`MONTH:(closeDate)` and `SUM:(amountConverted)` in the example above are complex expressions. [See more](../user-guide/complex-expressions.md) about them.\n\nIt's possible to build expressions with the *Expression* class (as of v7.0).\n\n```php\n<?php\nuse Espo\\ORM\\Query\\Part\\Expression as Expr;\n\n$queryBuilder->select(\n    Expr::if(\n        Expr::greaterOrEqual(Expr::column('opportunity.amount'), 1000),\n        '1000 or more',\n        'less than 1000'\n    ),\n    'alias'         \n);\n```\n\n```php\n<?php\nuse Espo\\ORM\\Query\\Part\\Expression as Expr;\n\n$queryBuilder->where(\n    Expr::greater(\n        Expr::column('opportunity.amount'),\n        1000\n    )\n);\n```\n\nIt's possible to add custom functions (as of v7.0.8). An implementation class name for a custom function should be defined in metadata by a path app > orm > platforms > Mysql > functionConverterClassNameMap. The class should implement `Espo\\ORM\\QueryComposer\\Part\\FunctionConverter` interface.\n\n## Query builder\n\nDelete:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\DeleteBuilder;\n\n$query = DeleteBuilder::create()\n    ->from('SomeTable')\n    ->where([\n        'someColumn' => 'someValue'\n    ])\n    ->build();\n\n$entityManager->getQueryExecutor()->execute($query);\n```\n\nSelect:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\SelectBuilder;\n\n$query = SelectBuilder::create()\n    ->select(['column1', 'column2', 'someExpression'])\n    ->from('SomeTable')    \n    ->order('column1', 'DESC')\n    ->limit(0, 10)\n    ->build();\n\n$pdoStatement = $entityManager->getQueryExecutor()->execute($query);\n```\n\n```php\n<?php\nuse Espo\\ORM\\Query\\SelectBuilder;\n\n$query = SelectBuilder::create()\n    ->select('SUM:(someColumn)', 'value')\n    ->from('SomeTable')    \n    ->select('anotherColumn')\n    ->groupBy('anotherColumn')\n    ->build();\n\n$pdoStatement = $entityManager->getQueryExecutor()->execute($query);\n$row = $pdoStatement->fetch();\n$sum = $row['value'] ?? 0.0;\n```\n\nUpdate:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\UpdateBuilder;\n\n$query = UpdateBuilder::create()\n    ->in('SomeTable')\n    ->set(['status' => 'Expired'])\n    ->where([\n        'status' => 'Pending',\n        'expiresAt' => $dateTimeString,\n    ])\n    ->build();\n\n$entityManager->getQueryExecutor()->execute($query);\n```\n\nUpdate with join (in PostgreSQL, a subquery will be used):\n\n```php\n<?php\nuse Espo\\ORM\\Query\\UpdateBuilder;\n\n$query = UpdateBuilder::create()\n    ->in('SomeTable')\n    ->set(['column:' => 'joinAlias.foreignColumn'])\n    ->join('AnotherTable', 'joinAlias', ['joinAlias.foreignId:' => 'id'])\n    ->where([\n        'someColumn' => 'someValue'\n    ])\n    ->build();\n\n$entityManager->getQueryExecutor()->execute($query);\n```\n\nInsert:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\InsertBuilder;\n\n$query = InsertBuilder::create()\n    ->into('SomeTable')\n    ->columns(['column1', 'column2'])\n    ->values([\n        'column1' => 'value1',\n        'column2' => 'value2',\n    ])\n    ->build();\n\n$entityManager->getQueryExecutor()->execute($query);\n```\n\nMass insert:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\InsertBuilder;\n\n$query = InsertBuilder::create()\n    ->into('SomeTable')\n    ->columns(['column'])\n    ->values([\n        ['column1' => 'value1'],\n        ['column2' => 'value2'],\n    ])\n    ->build();\n\n$entityManager->getQueryExecutor()->execute($query);\n```\n\nMass insert by populating with a select sub-query:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\InsertBuilder;\n\n$query = InsertBuilder::create()\n    ->into('SomeTable')\n    ->columns(['column'])\n    ->valuesQuery($subQuery)\n    ->build();\n\n$entityManager->getQueryExecutor()->execute($query);\n```\n\nUnion:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\UnionBuilder;\n\n$query = UnionBuilder::create()\n    ->all()\n    ->query($subQuery1)\n    ->query($subQuery2)\n    ->order(1, 'DESC')\n    ->limit(0, 5)\n    ->build();\n\n$pdoStatement = $entityManager->getQueryExecutor()->execute($query);\n```\n\nCloning and modifying an existing query:\n\n```php\n<?php\nuse Espo\\ORM\\Query\\SelectBuilder;\n\n$clonedQuery = SelectBuilder::clone($query)\n    ->limit(0, 10)\n    ->build();\n```\n\n## Mass insert\n\nMass insert with Mapper:\n\n```php\n<?php\n$entityManager->getMapper()->massInsert($collection);\n```\n\n## Transaction manager\n\nTransaction:\n\n```php\n<?php\n$tm = $entityManager->getTransactionManager();\n\n$tm->start();\n\ntry {\n    // do something\n    $tm->commit();\n} catch (Throwable $e) {\n    $tm->rollback(); // this will roll back everything done within the transaction\n}\n```\n\nNested transactions:\n\n```php\n<?php\n$tm = $entityManager->getTransactionManager();\n\n$tm->start();\n// do something\n$tm->start();\n// do something\n$tm->commit();\n// do something\n$tm->commit();\n```\n\nRunning a function in a transaction:\n\n```php\n<?php\n$entityManager\n    ->getTransactionManager()\n    ->run(\n        function () {\n            // Transaction started implicitly.\n            // Do something.\n            // Transaction committed implicitly or rolled back if an exception occurred.\n        }\n    );\n```\n\nLocking:\n\n```php\n<?php\n$entityManager->getTransactionManager()->start();\n\n$entity = $entityManager\n    ->getRDBRepository('SomeTable')\n    ->where(['id' => $id])\n    ->forUpdate() // This will lock the selected rows until the transaction is finished.\n    ->findOne();\n\n// Do something with the entity.\n\n$entityManager->saveEntity($entity);\n\n$entityManager->getTransactionManager()->commit();\n```\n\n## Locker\n\n```php\n<?php\n// This will start a transaction implicitly and lock the table.\n$entityManager->getLocker()->lockExclusive('SomeEntityType');\n\n// Do something.\n\n// This will unlock all locked tables.\n$entityManager->getLocker()->commit();\n```\n\n## Defs\n\n*As of v7.0.*\n\nAn access point to read ORM metadata: entity, attribute, field, relation and index definitions.\n\n```php\n<?php\n$defs = $entityManager->getDefs();\n```\n\nORM Defs can also be required as a dependency so that it will be injected into your class. Use the type hint `Espo\\ORM\\Defs`.\n\nCheck entity existence:\n\n```php\n<?php\n$entityExists = $defs->hasEntity($entityType);\n```\n\nEntity defs:\n\n```php\n<?php\n$entityDefs = $defs->getEntity($entityType);\n```\n\nAn attribute list:\n\n```php\n<?php\n$attributeList = $entityDefs->getAttributeNameList();\n```\n\nAttribute defs:\n\n```php\n<?php\n$attributeDefs = $entityDefs->getAttribute($attributeName);\n```\n\nA relation list:\n\n```php\n<?php\n$relationList = $entityDefs->getRelationNameList();\n```\n\nRelation defs:\n\n```php\n<?php\n$relationDefs = $entityDefs->getRelation($relationName);\n```\n\nA field list:\n\n```php\n<?php\n$fieldList = $entityDefs->getFieldNameList();\n```\n\nField defs:\n\n```php\n<?php\n$fieldDefs = $entityDefs->getField($field);\n```\n\nSee all available methods in:\n\n* `Espo\\ORM\\Defs\\EntityDefs`\n* `Espo\\ORM\\Defs\\AttributeDefs`\n* `Espo\\ORM\\Defs\\RelationDefs`\n* `Espo\\ORM\\Defs\\FieldDefs`\n* `Espo\\ORM\\Defs\\IndexDefs`\n\nAttribute types:\n\n* `Entity::ID`\n* `Entity::VARCHAR`\n* `Entity::INT`\n* `Entity::FLOAT`\n* `Entity::TEXT`\n* `Entity::VARCHAR`\n* `Entity::FOREIGN`\n* `Entity::FOREIGN_ID`\n* `Entity::FOREIGN_TYPE`\n* `Entity::DATE`\n* `Entity::DATETIME`\n* `Entity::JSON_ARRAY`\n\nRelation types:\n\n* `Entity::MANY_MANY`\n* `Entity::HAS_MANY`\n* `Entity::BELONGS_TO`\n* `Entity::HAS_ONE`\n* `Entity::BELONGS_TO_PARENT`\n* `Entity::HAS_CHILDREN`\n* `Entity::JSON_OBJECT`\n\n"
  },
  {
    "path": "docs/development/quote-custom-calculations.md",
    "content": "# Custom calculations for Quote totals\n\n!!! warning\n\n    This method is not recommended anymore as it's likely to cause problems. Since this article has been written, the functionality has been significantly extended to support more complex financial calculations. Changing the calculated amount in the hook will likely break the calculation logic.\n\nNote: The same mechanism is also available for Sales Orders and Invoices.\n\n## Problem\n\nYou have added custom fields to quote items or/and quote entity types. You want Total Amount field and other totals to be calculated considering new custom fields.\n\n## Resolution\n\n### Server-side calculation\n\nYou need to create a custom Hook for the Quote entity type.\n\nCreate a new file:\n\n`custom/Espo/Custom/Hooks/Quote/CalculateItems.php`\n\n```php\n<?php\nnamespace Espo\\Custom\\Hooks\\Quote;\n\nuse Espo\\ORM\\Entity;\n\nclass CalculateItems\n{    \n    public static int $order = 10;\n\n    public function __construct(\n        // Define needed dependencies.\n    ) {}\n\n    public function beforeSave(Entity $entity, array $options): void\n    {\n        if (!$entity->has('itemList')) {\n             $entity->loadItemListField();\n        }\n\n        $itemList = $entity->get('itemList');\n\n        $amount = 0.0;\n        foreach ($itemList as $item) {\n            $amount +=  $item->quantity * $item->unitPrice * $item->factor;\n        }\n        $entity->set('amount', $amount);\n    }\n}​\n```\n\nNote: For other entity types, e.g. SalesOrder, do the same but use *SalesOrder* namespace and file location instead of *Quote*.\n\n### Client-side calculation\n\nIn Quote's clientDefs you need to specify custom calculation handler:\n\nFile: `custom/Espo/Custom/Resources/metadata/clientDefs/Quote.json`\n\n```json\n{\n    \"calculationHandler\": \"custom:quote-calculation-handler\"\n}\n```\n\nNote: For Sales Orders use `SalesOrder.json` file names.  For Invoices use `Invoice.json` file names.\n\nCreate a new file:\n\n`client/custom/src/quote-calculation-handler.js`\n\n```js\ndefine(['sales:quote-calculation-handler'], (Dep) => {\n\n    return class extends Dep {\n\n        // Define custom calculations here.\n        // Use client/modules/sales/quote-calculation-handler.js as an example.\n\n        /**\n         * Calculate.\n         *\n         * @param {import('model').default} model An order.\n         */\n        calculate(model) {\n            super.calculate(model);\n        }\n\n        /**\n         * Calculate item.\n         *\n         * @param {import('model').default} model An item.\n         * @param {string} [field] A field that was changed.\n         */\n        calculateItem(model, field) {\n            super.calculateItem(model, field);\n        }\n\n        /**\n         * Select product.\n         *\n         * @param {import('model').default} model\n         * @param {import('model').default} product\n         */\n        selectProduct(model, product) {\n            super.selectProduct(model, product);\n        }\n\n        /**\n         * Get select product attributes.\n         *\n         * @param {import('model').default} model\n         * @return {string[]}\n         */\n        getSelectProductAttributeList(model) {\n            super.getSelectProductAttributeList(model);\n        }\n    }\n});\n```\n\nIt's also possible to make certain product fields copied to a quote item on product selection. The logic is determined in selectProduct method.\n\n"
  },
  {
    "path": "docs/development/resources.md",
    "content": "# Resources\n\n>PATH is one of\n>1. CUSTOM_PATH - custom/Espo/Custom/Resources;\n>2. MODULE_PATH - application/Espo/Modules/{ModuleName}/Resources;\n>3. BASE_PATH - application/Espo/Resources\n\nIn Resources folder you can find such items:\n\n## i18n\n\nTranslation.\n\n{language_name} - [language code in ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1)_[country code in ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)\n\n`{PATH}/i18n/{language_name}/{EntityName}.json`\n\n\n## layouts\n\nLayouts of entities.\n\n`{PATH}/layouts/{EntityName}/{layoutName}.json`\n\n[Layout Manager](../administration/layout-manager.md)\n\n\n## metadata\n\nMetadata.\n\n## templates\n\nHere contains templates, are using for emailing.\n\n`{PATH}/templates/{templateGroup}/{language_code}/{templateName}.tpl`\n\n\n## routes\n\n`{PATH}/routes.json`\n"
  },
  {
    "path": "docs/development/scheduled-job.md",
    "content": "# Scheduled Jobs\n\n## Creating custom scheduled job\n\nCreate a file `custom/Espo/Custom/Resources/metadata/app/scheduledJobs.json`:\n\n```json\n{\n    \"YourJobName\": {\n    \t\"jobClassName\": \"Espo\\\\Custom\\\\Jobs\\\\YourJobName\"\n    }\n}\n```\n\nCreate a file `custom/Espo/Custom/Jobs/YourJobName.php` with the content.\n\n```php\n<?php\n\nnamespace Espo\\Custom\\Jobs;\n\nuse Espo\\Core\\Job\\JobDataLess;\n\nclass YourJobName implements JobDataLess\n{\n    // Pass dependencies through the constructor using DI.\n    public function __construct()\n    {\n    }\n    \n    public function run(): void \n    {\t \n\t// Write your logic here.\n    }\t \n}\n```\n\nAlso, you can set a label for your job (`custom/Espo/Custom/Resources/i18n/en_US/ScheduledJob.json`).\n\n```json\n{\n   \"options\": { \n       \"job\": { \n           \"YourJobName\": \"Your Job Label\"\n       }\n   }\n}\n```\n\nTo make the changes applied, clear cache at Administration.\n\nNow, you can create a scheduled job at Administration > Scheduled Jobs. *YourJobName* will be available in the picklist.\n\nYou can also run your job **from CLI**:\n\n```\nbin/command run-job YourJobName\n```\n"
  },
  {
    "path": "docs/development/select-builder.md",
    "content": "# Select Builder\n\n*As of v7.0.*\n\nThe Select Builder builds select queries for the ORM. It applies search parameters (passed from the frontend), access control restrictions, text filters, bool filters, primary filters. It's utilized as a layer over the ORM, since the ORM does not know anything about access control, predefined filters. It does not know how to handle text filters. As well as it does not understand the format of search parameters passed from the frontend.\n\nSee all available methods in the class `Espo\\Core\\Select\\SelectBuilder`.\n\nUsage example (building a query):\n\n```php\n<?php\n$selectBuilder = $this->selectBuilderFactory->create();\n\n$query = $selectBuilder\n    ->from($entityType)\n    ->withStrictAccessControl() // applies ACL\n    ->withSearchParams($searchParams) // search parameters passed from the frontend\n    ->build();\n\n$collection = $this->entityManager\n    ->getRDBRepository($entityType)\n    ->clone($query)\n    ->find();\n```\n\nUsage example (building a query builder):\n\n```php\n<?php\n$query = $selectBuilder\n    ->from($entityType)\n    ->withPrimaryFilter($primaryFilter)\n    ->buildQueryBuilder() // to continue building by means of ORM\n    ->where([\n        'someAttribute' => $someValue,\n    ])\n    ->build();\n```\n\nUsage example (another user):\n\n```php\n<?php\n$query = $selectBuilder\n    ->from($entityType)\n    ->forUser($user) // to apply access control for another user\n    ->withStrictAccessControl()\n    ->build();\n```\n\nIn your class you need to require `Espo\\Core\\Select\\SelectBuilderFactory` as a dependency.\n\n```php\n<?php\nnamespace Espo\\Custom\\SomeNamespace;\n\nuse Espo\\Core\\Select\\SelectBuilderFactory;\n\nclass SomeClass\n{    \n    public function __construct(private SelectBuilderFactory $selectBuilderFactory)\n    {}\n}\n```\n\nOnce you built a query you can pass it to the repository:\n\n```php\n<?php\n$collection = $entityManager\n    ->getRDBRepository($entityType)\n    ->clone($query)\n    ->find();\n```\n\nOr you can pass it to the QueryExecutor:\n\n```php\n<?php\n$sth = $entityManager->getQueryExecutor()->execute($query);\n```\n\n## Search Params\n\nSearch parameters. Usually passed from the frontend. The SearchParams object contains a primary filter, bool filters, text filter, where conditions, offset, limit, order, and what columns to select. When a frontend collection is fetched, search parameters are passed in the request.\n\nClass: `Espo\\Core\\Select\\SearchParams`.\n\nA SearchParams object can be fetched from a Request object by using `Espo\\Core\\Record\\SearchParamsFetcher`. Usually it's done in API action classes.\n\n```php\n<?php\nnamespace Espo\\Custom\\Api;\n\nuse Espo\\Core\\Api\\Action;\nuse Espo\\Core\\Api\\Request;\nuse Espo\\Core\\Api\\Response;\nuse Espo\\Core\\Record\\SearchParamsFetcher;\n\nclass MyAction extends Action\n{\n    public function __construct(\n        private SearchParamsFetcher $searchParamsFetcher,\n    ) {}\n\n    public function process(Request $request): Response\n    {\n        $searchParams = $searchParams = $this->searchParamsFetcher->fetch($request);\n\n        // ...\n    }\n}\n```\n\n## See also\n\n* [Definitions of Select framework, metadata > selectDefs](metadata/select-defs.md)\n\n"
  },
  {
    "path": "docs/development/select-manager.md",
    "content": "# Select Manager\n\nImportant: Deprecated as of v6.1.0. Use Select Builder instead.\n\nSelect Manager can be utilized for generating and managing select params which subsequently will be feed to ORM.\n\nBase class: [Base.php](https://github.com/espocrm/espocrm/blob/stable/application/Espo/Core/SelectManagers/Base.php).\n\nUsage example:\n\n```php\n$selectManager = $selectManagerFactory->create('Opportunity');\n$params = $selectManager->getEmptySelectParams();\n\n$selectManager->applyAccess($params); // add ACL $params\n$selectManager->applyPrimaryFilter('open', $params);\n$selectManager->applyOrder('createdAt', true, $params);\n$selectManager->applyLimit(0, 5, $params);\n\n$params['whereClause'][] = [\n    'accountId' => $accountId,\n];\n\n$entityManager->getRepository('Opportunity')->find($params);\n```\n\n### Creating an instance of Select Manager\n\n```php\n$selectManager = $container->get('selectManagerFactory')->create($entityType);\n```\n\nFor a specific user, to be able to apply ACL specific to the user.\n\n```php\n$selectManager = $container->get('selectManagerFactory')->create($entityType, $user);\n```\n\n### Generating empty select params\n\n```php\n$params = $selectManager->getEmptySelectParams();\n```\n\n### Applying ACL\n\n```php\n$selectManager->applyAccess($params);\n```\n\n### Primary filter\n\n```php\n$selectManager->applyPrimaryFilter($filterName, $params);\n```\n\n### Bool filter\n\n```php\n$selectManager->applyBoolFilter($filterName, $params);\n```\n\n### Distinct\n\n```php\n$selectManager->setDistinct(true, $params);\n```\n\n### Add Join\n\n```php\n$selectManager->addJoin([\n    'linkName',\n    'someAlias',\n], $params);\n```\n\n```php\n$selectManager->addJoin([\n    'TableName', // table name in CamelCase\n    'someAlias', // alias for our join\n    [\n        'someAlias.meetingId:' => 'id', // additional join condition\n    ]\n], $params);\n```\n\n### Add Left Join\n\n\n```php\n$selectManager->addLeftJoin([\n    'linkName',\n    'someAlias',\n], $params);\n```\n\n## Custom Select Manager\n\nHow to extend an existing select manager for a specific entity type.\n\nExample for *Account*. There is already extended class in `application/Espo/Modules/Crm/SelectManagers/Account.php`, so we need to extend from it.\n\nCreate a file `custom/Espo/Custom/SelectManager/Account.php`:\n\n```php\n<?php\nnamespace Espo\\Custom\\SelectManagers;\n\nclass Account extends \\Espo\\Modules\\Crm\\SelectManagers\\Account\n{\n    protected function filterMyCustomFilter(&$result)\n    {\n        $result['whereClause'][] = [\n            'someAttribute' => 'Some Value',\n        ];\n    }\n}\n```\n\nIf there's no select manager class for a specific entity type, you need to extend from `\\Espo\\Core\\SelectManagers\\Base`.\n"
  },
  {
    "path": "docs/development/services.md",
    "content": "# Service Classes\n\n!!! note\n\n    Not to be confused with [*Container services*](di.md).\n\nServices are entry points for business logic. They are just regular PHP classes. You can write business logic right in a service class or delegate it inside the service to another classes. Controllers and Action classes are supposed to have little code. Usually, they call service methods.\n\nYou can create a service class in any namespace you like (inside your module). Use the dependency injection to require this class in your Controller or Action class (your class will be passed to a constructor).\n\n## Creating service class\n\nController `custom/Espo/Custom/Controllers/SomeController.php`:\n\n```php\n<?php\nnamespace Espo\\Custom\\Controllers;\n\nuse Espo\\Core\\Exceptions\\BadRequest;\nuse Espo\\Core\\Api\\Request;\nuse Espo\\Core\\Api\\Response;\nuse Espo\\Custom\\MyNamespace\\MyService;\n\nclass SomeController\n{\n    public function __construct(private MyService $myService)\n    {}\n\n    public function postActionHello(Request $request, Response $response): void\n    {\n        $data = $request->getParsedBody();\n        \n        $id = $data->id ?? null;\n        \n        if (!$id) {\n            throw new BadRequest();\n        }\n\n        $this->myService->doSomething($id);\n        \n        $response->writeBody('true');\n    }\n}\n```\n\nService `custom/Espo/Custom/MyNamespace/MyService.php`:\n\n```php\n<?php\nnamespace Espo\\Custom\\MyNamespace;\n\nuse Espo\\Core\\Exceptions\\Forbidden;\nuse Espo\\Core\\Exceptions\\NotFound;\nuse Espo\\Core\\Acl;\nuse Espo\\Core\\Acl\\Table;\nuse Espo\\ORM\\EntityManager;\nuse Espo\\Modules\\Entities\\Opportunity;\n\nclass MyService\n{\n    public function __construct(private Acl $acl, private EntityManager $entityManager)\n    {}\n\n    public function doSomething(string $id): void\n    {\n        $opportunity = $this->entityManager->getEntityById(Opportunity::ENTITY_TYPE, $id);\n\n        if (!$opportunity) {\n            throw new NotFound();\n        }\n\n        if (!$this->acl->check($opportunity, Table::ACTION_EDIT)) {\n            throw new Forbidden(\"No 'edit' access.\");\n        }\n\n        $opportunity->set('stage', Opportunity::STATUS_CLOSED_WON);\n        $opportunity->set('probability', 100);\n\n        $this->entityManager->saveEntity($opportunity);\n    }\n}\n```\n\n## Record service\n\nThe Record Service is a layer to access records via API. It handles CRUD (and some others) operations over entities (records). It applies validation and access checks before saving or reading.\n\nThe base class `Espo\\Core\\Record\\Service`.\n\nMain methods of the Record service class:\n\n* read – get an entity\n* create – create an entity\n* update – update an entity\n* delete – delete an entity\n* find – get a list of entities, used by list view\n* findLinked – get a list of related entities, used by relationship panels\n* loadAdditionalFields – to load additional fields for an entity before returning it, for detail view\n\n!!! note\n    \n    Record services can be extended in the `Espo\\Modules\\{MyModule}\\Services` namespace. But it's recommended to avoid extending.\n    The framework allows customization by means of composition. See metadata > [recordDefs](metadata/record-defs.md).\n\n### Accessing record service\n\nRecord services can be accessed from the record service container `Espo\\Core\\Record\\ServiceContainer`.\n\n```php\n<?php\n$service = $this->recordServiceContainer->get($entityType);\n```\n"
  },
  {
    "path": "docs/development/template-custom-helper.md",
    "content": "# Custom Template Helpers\n\n*As of v7.0.*\n\nHelpers works for PDF templates and system email templates (Administration > Template Manager).\n\n\nCreate a file `custom/Espo/Custom/Resources/metadata/app/templateHelpers.json`:\n\n```json\n{\n    \"myHelper\": \"Espo\\\\Custom\\\\TemplateHelpers\\\\MyHelper\"\n}\n```\n\nCreate a file `custom/Espo/Custom/TemplateHelpers/MyHelper.php`:\n\n```php\n<?php\nnamespace Espo\\Custom\\TemplateHelpers;\n\nuse Espo\\Core\\Htmlizer\\Helper;\nuse Espo\\Core\\Htmlizer\\Helper\\Data;\nuse Espo\\Core\\Htmlizer\\Helper\\Result;\n\nclass MyHelper implements Helper\n{\n    public function __construct(\n        // Pass needed dependencies.\n    ) {\n\n    }\n    \n    public function render(Data $data): Result\n    {\n        $color = $data->getOption('color');        \n        $text = $data->getArgumentList()[0] ?? '';        \n        \n        return Result::createSafeString(\n            \"<span style=\\\"color: {$color};\\\">\" . $text . \"</span>\"\n        );\n    }\n}\n```\n\nClear cache.\n\nThen, in a template, you can use:\n\n```\n{{myHelper 'some text' color='#bd318e'}}\n```\n\n"
  },
  {
    "path": "docs/development/tests.md",
    "content": "# Tests\n\n## Unit tests\n\n\nCommand to run:\n\n```\nvendor/bin/phpunit\n```\n\n## Integration tests\n\nCreate a database for testing.\n\nCreate a config file  `tests/integration/config.php`:\n\n```php\n<?php\nreturn [\n    'database' => [\n        'driver' => 'pdo_mysql',\n        'host' => 'localhost',\n        'port' => '',\n        'charset' => 'utf8mb4',\n        'dbname' => 'TEST_DATABASE_NAME',\n        'user' => 'DATABASE_USER',\n        'password' => 'DATABASE_PASSWORD',\n    ],\n];\n```\n\nThis config will be used for test instances that are built for each test.\n\n\nBefore running tests, you need to build for testing:\n\n```\ngrunt test\n```\n\nRunning tests:\n```\nvendor/bin/phpunit tests/integration\n```\n\n## Static analysis\n\nCommand to run:\n\n```\nvendor/bin/phpstan\n```\n"
  },
  {
    "path": "docs/development/translation.md",
    "content": "# Translation\n\n## PO file\n\n### Generating PO file\n\nYou need to have node installed and installed project dependencies with `npm install`.\n\nBuild po file with the following command:\n\n```\nnode po.js en_EN\n```\n\n(specify the needed language instead of en_EN)\n\nThe file will be created in the `build` directory.\n\nAfter that you can translate the generated po file. You can use some utilities or service for PO file translating. \n\n### Building language files from PO file\n\nBuild json files from the translated po file:\n\n1. Put your po file espocrm-en_EN.po into `build` directory\n2. Run `node lang.js en_EN`\n\n(use your language instead of en_EN)\n\nJson files will be created in `build` directory grouped by folders.\n\nYou can test your translation by copying generated JSON files into your EspoCRM directory.\n\n## Adding new language\n\nThe available language list is specified in metadata > app > language.\n\nTo add a new language create a file `custom/Espo/Custom/Resources/metadata/app/language.json`:\n\n```json\n{\n    \"list\": [\n        \"__APPEND__\",\n        \"lg_CN\"\n    ]\n}\n```\n\nWhere *lg_LG* is a IETF language tag. 'lg' is the language code specified by ISO 639, 'CN' is a country code specified by ISO 3166.\n\nClear cache after that (Administration > Clear Cache). The language will be available at Administration > Settings and user's preferences.\n"
  },
  {
    "path": "docs/development/view.md",
    "content": "# View\n\nThe View is the most often used class in the frontend. Every page is rendered by multiple view objects. Views can have child views. Child views can have their own child views and so on. When a parent view is rendered (by calling the `render` method), it generates a single HTML and adds it to the DOM. That HTML contains HTML of all child views. Any view can be re-rendered later.\n\nA view file `client/custom/src/views/test/my-custom-view.js`:\n\n```js\n// AMD module definition (ES modules are supported in ext-template). The first argument can be omitted.\n// Names should be in a lower case. A hyphen to be used for word separation.\n// The `custom:` prefix indicates to the loader that the base path is `client/custom/src`.\n// A `my-module:` prefix would correspond to `client/custom/modules/my-module/src`.\ndefine('custom:views/test/my-custom-view', ['view'], (View) => {\n\n    // Extending from the base `view` class.\n    return class extends View {\n\n        // Optionally, define an extended constructor.\n        constructor(options) {\n            super(options);\n        }\n\n        // A template. See the separate article about templates.\n        // language=Handlebars\n        templateContent = `\n            <div class=\"some-test-container\">{{{someKeyName}}}</div>            \n            <p>{{viewObject.someParam1}}</p>\n            <p>{{someParam2}}</p>\n            <p><a class=\"action\" data-action=\"test\">Test Action</a></p>            \n            <div class=\"another-test-container\"></div>\n        `\n\n        // Alternatively, a template can be defined in a separate file.\n        // The `custom` prefix indicates that the base path is `client/custom/res/templates`.        \n        //template = 'custom:test/my-custom-view'\n\n        // Initializing. Called on view creation, the view is not yet rendered.\n        setup() {\n            // Calling the parent `setup` method, can be omitted.\n            super.setup();\n            \n            // Instantiate some property.\n            this.someParam1 = 'test 1';\n\n            this.addHandler('focus', '.record input[data-name=\"hello\"]', (event, target) => {\n                // Do something.\n            });\n\n            // When we create a child view in the setup method, rendering of the view is held off\n            // until the child view is loaded (ready), the child view will be rendered along with the parent view.\n            // The first argument is a key name that can be used to access the view further.\n            // The second argument is a view name.\n            // The method returns a promise that resolves to a view object.\n            this.createView('someKeyName', 'custom:test/my-custom-child-view', {\n                // A relative selector of the DOM container.\n                selector: '.some-test-container',\n                // Or a full selector.\n                //fullSelector: '#some-id',\n                // Pass some parameter.\n                someParam: 'test',\n            }); \n            \n            // Options passed from the parent view.\n            console.log(this.options); \n            \n            // A model can be passed from the parent view.\n            console.log(this.model);\n            \n            // All event listeners are recommended to be initialized in the `setup` method.\n\n            // Use listenTo & listenToOnce methods for listening to events of another object\n            // to prevent memory leakage.\n\n            // Subscribe to model change.\n            // Subscribing with the `listenTo` method guarantees automatic unsubscribing on view removal,\n            // so there won't be a memory leak.\n            this.listenTo(this.model, 'change', () => {\n                // Whether a specific attribute changed.\n                if (this.model.hasChanged('someAttribute')) {\n                    const value = this.model.get('someAttribute');\n                }\n            });\n            \n            // Subscribe to model sync (saved or fetched). Fired only once.\n            this.listenToOnce(this.model, 'sync', () => {});\n            \n            // Subscribe to a DOM event. `cid` contains an ID unique among all views.\n            // Requires explicit unsubscribing on view removal.\n            $(window).on('some-event.' + this.cid, () => {});\n\n            // Translating a label.\n            const translatedLabel = this.translate('myLabel', 'someCategory', 'MyScope');\n        }\n\n        // Called after contents is added to the DOM.\n        afterRender() {            \n            // The view container (DOM element).\n            console.log(this.element); \n            \n            // Accessing a child view.\n            const childView = this.getView('someKeyName');\n            \n            // Checking whether a view is set.\n            const hasSomeView = this.hasView('someKeyName');\n            \n            // Destroying a child view, also removes it from DOM.\n            this.clearView('someKeyName');\n            \n            // Initializing a reference to some DOM element.\n            this.$someElement = this.$el.find('.some-element');\n        }\n        \n        // Data to be passed to the template.\n        data() {\n            return {\n                someParam2: 'test 2',\n            };\n        }\n        \n        // Called when the view is removed.\n        // Useful for destroying event listeners initialized for the view.\n        onRemove() {\n            $(window).off('some-event.' + this.cid);\n        }\n        \n        // A custom method.\n        someMethod1(value) {\n            // Create and render a child view.\n            this.createView('testKey', 'custom:test/my-another-custom-child-view', {\n                selector: '.another-test-container', \n                value: value,\n            })\n            .then(view => view.render());\n        }\n        \n        someMethod2() {\n            // To proceed only when the view is rendered.\n            // Useful when the method can be invoked by a caller before the view is rendered.\n            this.whenRendered().then(() => {\n                // Do something with DOM.\n            });\n        }\n    }\n}\n```\n\nSee more about [templates](frontend/templates.md).\n\nSee [the source file](https://github.com/yurikuzn/bull/blob/master/src/bull.view.js) of the view class.\n\n## Waiting for some data loaded before rendering\n\nSometimes we need to get some data loaded asynchronously before the view is rendered. For this purpose we can use the `wait` method inside the `setup` method. \n\nThe `wait` method can receive a promise:\n\n```js\nsetup() {\n    this.wait(\n        Promise.all([\n            this.model.fetch(),\n            this.model.collection.fetch(),\n        ])\n    );\n}\n```\n\nThe model factory returns a promise, so we can pass it to the `view` method:\n\n```js\nsetup() {\n    this.wait(\n        this.getModelFactory().create('Case')\n            .then(model => {\n                model.id = this.model.id;\n\n                return model.fetch();\n            })\n            .then(data => {\n                console.log(data);\n            })\n    );\n}\n```\n\nWait until a model is fetched. The `fetch` method returns a promise.\n\n```js\nsetup() {\n    this.wait(\n        this.model.fetch()\n    );\n}\n```\n\nWait for multiple independent promises:\n\n```js\nsetup() {\n    this.wait(\n        this.model.fetch()\n    );\n    \n    this.wait(\n        Espo.Ajax.getRequest('SomeUrl')\n    );\n}\n```\n\n```js\nsetup() {\n    this.wait(\n        Promise.all([\n            this.model.fetch(),\n            Espo.Ajax.getRequest('SomeUrl'),\n        ])\n    );\n}\n```\n\nA simple way to wait:\n\n```js\nsetup() {\n    // This holds off the rendering.\n    this.wait(true);\n\n    Espo.Ajax.getRequest('Some/Request')\n        .then(response => {\n            // This cancels waiting and proceeds to rendering.\n            this.wait(false);                \n        });\n}\n```\n\n!!! note\n\n    Feel free to use the async/await syntax instead of explicit promises.\n\n### setup\n\nCalled internally on initialization. Put initialization logic here. Options passed by the parent view are available in `this.options`.\n\n### afterRender\n\nCalled internally after render. Put manipulation with DOM here.\n\n### onRemove\n\nCalled internally on view removal. Reasonable for unsubscribing.\n\n### createView\n\nCreates a child view. When we create a child view in the setup method, rendering of the view is held off until the child view is loaded (ready), the child view will be rendered along with the parent view. The first argument is a key name that can be used to access the view further (with `getView` method). The second argument is a view name. The method returns a promise that resolves to a view object.\n\nArguments:\n\n* *viewKey* – a view key;\n* *viewName* – a view name (path);\n* *options* – options.\n\nStandard options (all are optional):\n\n* *selector* – a relative CSS to the view selector (as of v7.3);\n* *model* – a model;\n* *collection* – a collection.\n\nIt's important that every view have their actual selector so that the application knows how to access them (for re-rendering).\n\n### clearView\n\nRemoves a child view.\n\nArguments:\n\n* *viewKey* – a view key.\n\n### getView\n\nGet a child view by a key.\n\nArguments:\n\n* *viewKey* – a view key.\n\n### assignView\n\n*As of v7.5.*\n\nAssign a view instance as a child view.\n\nArguments:\n\n* *viewKey* – a view key;\n* *view* – a view instance;\n* *selector* – a relative CSS selector.\n\n```js\nthis.assignView('someKey', new SomeView(options), 'some-selector');\n```\n\n### reRender\n\nRe-renders a view. Usually, called from inside the view. Returns a promise resolved once rendering is finished.\n\nArguments:\n\n* *force* – *boolean* – force rendering if the view was not rendered before.\n\n### render\n\nRenders a view. Should be called if the view is called not in the *setup* method (after the view is already ready or rendered). Returns a promise resolved once rendering is finished.\n\n```js\ntemplateContent = `\n    <div data-name=\"someName\">{{{someKeyName}}}</div>\n`\n\nsetup() {\n    this.createView('someKeyName', 'custom:test/my-custom-child-view', {}); \n}\n\nasync actionShowModal() {\n    const view = await this.createView('dialog', 'custom:test/my-modal-view', {selector: '[data-name=\"someName]'})\n    \n    this.listenToOnce(view, 'some-event', eventData => {\n        console.log(eventData);\n        \n        this.clearView('dialog');\n    });\n\n    await view.render();\n}\n```\n\n### whenRendered\n\nReturns the promise resolving when the view is rendered.\n\n```js\nthis.whenRendered().then(() => doSomethingWithDom());\n```\n\n### data\n\nThe method is called internally when rendering. Should return a key => value data (*Object.<string, mixed>*) that will be passed to a template.\n\n\n### addHandler\n\n*As of v8.0.*\n\nAdds a DOM event handler.\n\n```js\nthis.addHandler('click', 'selector', 'methodName');\nthis.addHandler('mousedown', 'selector', (event, target) => { ... });\n```\n\n## Events\n\n```js\nsetup() {\n    // Use this way only when the view subscribes to self.\n    this.on(eventName, callback); // subscribe to self\n    this.once(eventName, callback); // subscribe once\n    this.off(eventName, callback); // unsubscribe\n    \n    // Use this way to subscribe to another object. Prevents memory leaking.\n    this.listenTo(object, eventName, callback); // subscribe to another object\n    this.listenToOnce(object, eventName, callback); \n    this.stopListening(object, eventName); // unsubscribe\n    \n    // Triggering event.\n    this.trigger(eventName);  \n    this.trigger(eventName, objectWithEventData); // passing data        \n}\n```\n\nMultiple events can be specified separated by a whitespace.\n\n### Built-in events\n\n* `after:render` – after the view is rendered;\n* `remove` – when the view is removed (destroyed); use it for cleaning up.\n"
  },
  {
    "path": "docs/development/workflow-service-actions.md",
    "content": "# Adding custom service action for Workflows\n\nWorkflows allow to create custom service actions. This example will show how this can be done for a Call entity.\n\n*As of Advanced Pack v3.2.3.*\n\n## Step 1. Create a class\n\n```php\n<?php\n \nnamespace Espo\\Custom\\ServiceActions;\n \nuse Espo\\ORM\\Entity;\nuse Espo\\Modules\\Advanced\\Tools\\Workflow\\Action\\RunAction\\ServiceAction;\n\nclass TestAction implements ServiceAction\n{\n    // Pass dependencies via constructor.\n\n    public function run(Entity $entity, mixed $data): mixed\n    {\n        // your code here\n\n        return null;\n    }\n}\n```\n\n## Step 2. Define the run service method in metadata\n\nCreate/edit the file `custom/Espo/Custom/Resources/metadata/app/workflow.json`\n\n```json\n{\n    \"serviceActions\": {\n        \"Call\":{\n            \"testAction\": {\n                \"className\": \"Espo\\\\Custom\\\\ServiceActions\\\\TestAction\"\n            }\n        }\n    }\n}\n```\n\nNote: You can also create the metadata file *workflow.json* file in your module directory.\n\n## Step 3. Add a label\n\nAdd or edit (if file exists) the file `custom/Espo/Custom/Resources/i18n/en_US/Workflow.json`.\n\n```json\n{\n    \"serviceActions\": {\n        \"testAction\": \"My Test Action\"\n    }\n}\n```\n\nOr if you have the same method name for several entity types, you can define different translation for them.\n\n```json\n{\n    \"serviceActions\": {\n        \"CallTestAction\": \"My Test Action for Call\",\n        \"TaskTestAction\": \"My Test Action for Task\"\n    }\n}\n```\nNote: You can also create a language file Workflow.json file in your module directory.\n\n## Step 4. Add usage tips (optional)\n\nAdd or edit the file `custom/Espo/Custom/Resources/i18n/en_US/Workflow.json`.\n\n```json\n{\n    \"serviceActionsHelp\": {\n        \"testAction\": \"A description.\"\n    }\n}\n```\n\nOr if you have the same method name for several entity types, you can define different tips xts for them.\n\n```json\n{\n    \"serviceActionsHelp\": {\n        \"CallTesAction\": \"...\",\n        \"TaskTestAction\": \"...\"\n    }\n}\n```\n\n## Step 5. Clear cache\n\nAdministration panel > Clear Cache. Now the service action is available for Workflows in the *Run Service Action* form.\n"
  },
  {
    "path": "docs/extensions/advanced-pack/overview.md",
    "content": "# Advanced Pack Overview\n\nAdvanced Pack is an [extension](https://www.espocrm.com/extensions/advanced-pack/) for EspoCRM.\n\nFeatures:\n\n* [Reports](../../user-guide/reports.md) – analytics, report panels and custom list view filters;\n* [Workflows](../../administration/workflows.md) – automation rules;\n* [BPM](../../administration/bpm.md) – business process management – automation with flowcharts.\n"
  },
  {
    "path": "docs/extensions/export-import/compare.md",
    "content": "# Compare changes\n\nThe export feature is available in the [Export Import](https://github.com/espocrm/ext-export-import/releases) extension.\n\n## Usage\n\nIn order to use the compare feature, you need to have an exported data (e.g. from a backup).\n\nThis extension works via console (CLI). Commands should be executed from the `root directory` of your EspoCRM instance.\n\n```bash\nbin/command export-import compare --format=json --path=\"./data/export-import\" --result-path=\"./data/export-import-result\" --compare-type=\"all\" --entity-list=\"Account\" --skip-related-entities --pretty-print --info\n```\n\n## Result\n\nThe result will be in a JSON format, so you can use `Total Commander`, `Double Commander` or even `git` to compare the results.\n\n### Statuses\n\nFor each entity, the following statuses may be shown:\n\n* `Total`: total number of compared records.\n* `Created`: number of created records.\n* `Modified`: number of modified records.\n* `Skipped (both modified)`: number of modified records that have already been modified by another user or workflow. This is where records can be checked manually. To enable this folder, use [`--info`](#-info) and [`--from-date`](#-from-date) options.\n* `Unmodified`: number of unmodified records.\n* `Deleted`: number of deleted records.\n\n### Data structure\n\nThis folder will contain data in a separate sub-folders:\n\n```\n.\n├── changed\n│   ├── actual\n│   ├── prev\n├── skipped\n│   ├── actual\n│   ├── prev\n```\n\n* `changed` folder contains the changed data.\n* `skipped` folder contains the both modified data that is skipped based on modifications found in the `modifiedAt` attribute, `Stream`, `Action History` and `Workflow Log`. To enable this folder, use [`--info`](#-info) and [`--from-date`](#-from-date) options.\n\n## Available options\n\n#### `--y`\n\nConfirmation of running the import. By default, a prompt will be displayed.\n\n#### `--path`\n\nA path for earlier exported data. The default value is `./data/export-import`. Example: `--path=\"PATH\"`.\n\n#### `--result-path`\n\nA path for the comparison result. The default value is `./data/export-import-result`. Example: `--result-path=\"PATH\"`.\n\n#### `--compare-type`\n\nA compare type. By default will be compared `all` records. Example: `--compare-type=\"TYPE\"`.\n\nAvailable options:\n\n* `all`\n* `created`\n* `updated`\n* `deleted`\n\n#### `--skip-data`\n\nSkip comparison of changed data. By default, the data will be compared.\n\n#### `--skip-customization`\n\n**Note:** not yet implemented.\n\nSkip customization comparison made for the instance. By default, all customization will be compared.\n\n#### `--skip-config`\n\n**Note:** not yet implemented.\n\nSkip configuration comparison of the instance. By default, all configuration data will be compared.\n\n#### `--skip-internal-config`\n\n**Note:** not yet implemented.\n\nSkip comparison of internal configuration data which are stored at `config-internal.php`.\nUse [`--user-password`](import.md/#-user-password) in order to set a user password since the `passwordSalt` will not be exported / imported.\n\n#### `--entity-list`\n\n!!! note\n\n    - For advanced users only.\n    - The defined list will be imported only with data of `Many-to-One`, `One-to-One Right`, `Children-to-Parent` relationships.\n    - The `Many-to-Many`, `One-to-Many`, `One-to-One Left`, `Parent-to-Children` relationships for related entities should be defined in the list additionally.\n\nA list of Entity Type. If omitted, then all entity types are applied. Example: `--entity-list=\"ENTITY_TYPE1, ENTITY_TYPE2\"`\n\nSupported values:\n\n* a string, e.g. `\"Account\"`;\n* a string which is separated by a comma, e.g. `\"Account, Contact\"`.\n\n#### `--all-customization`\n\n**Note**: This option works along with the `--entity-list` option only.\n\nThis option allows you to compare all customization, ignoring the `--entity-list' option.\n\n#### `--skip-related-entities`\n\nSkip comparison of data and customization for related entities. This option is used in conjunction with `--entity-list`. By default, this option is `off`.\n\n#### `--pretty-print`\n\nStore data in a pretty print format. By default this option is `off`.\n\n#### `--info`\n\nDisplay information about skipped modifications. By default this option is `off`.\n\n#### `--from-date`\n\nThe date and time in UTC from which the comparison will be made. By default this option is `off`. Example: `--from-date=\"2025-01-01 00:00:00\"`\n\n#### `--skip-modified-at`\n\nSkip comparison of `modifiedAt` attribute. By default this option is `off`.\n\n#### `--skip-stream`\n\nSkip looking for modifications in a stream. By default this option is `off`.\n\n#### `--skip-action-history`\n\nSkip looking for modifications in Action History. By default this option is `off`.\n\n#### `--skip-workflow-log`\n\nSkip looking for modifications in Workflow Log. By default this option is `off`.\n\n#### `--skip-attribute-list`\n\nSkip comparison of attribute list. By default all attributes will be compared. Example: `--skip-attribute-list=\"name, Account.description, Call.firstName\"`.\n\nPossible values:\n\n* a global attribute, e.g. `\"name\"`.\n* a local attribute, e.g. `\"Account.description, Call.firstName\"`.\n\n#### `--user-skip-list`\n\nDefine a list of users to be skipped. The value can be a list of `ID` or `User Name`. Example: `--user-skip-list=\"admin\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"admin\"`,\n* `a string which is separated by a comma`, e.g. `\"admin, 65d34ab18e81e286e\"`.\n\n#### `--entity-skip-list`\n\nThis option allows you to compare data for defined entities. Example: `--entity-skip-list=\"ENTITY_TYPE\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"Account\"`,\n* `a string which is separated by a comma`, e.g. `\"Account, Contact\"`.\n\n#### `--entity-hard-list`\n\nThis option allows you to export or import data for entities which are disabled by default, in `exportImportDefs` with the `\"exportDisabled\": true` or `\"importDisabled\": true` option. Example: `--entity-hard-list=\"ENTITY_TYPE\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"ScheduledJob\"`,\n* `a string which is separated by a comma`, e.g. `\"ScheduledJob, ScheduledJobLogRecord\"`.\n\n#### `--config-hard-list`\n\n**Note:** not yet implemented.\n\nThis option allows you to compare data for config options which are disabled by default. Ex. `--config-hard-list=\"CONFIG_OPTION\"`.\nThe default list is defined in `application/Espo/Modules/ExportImport/Resources/metadata/app/exportImport.json`.\n\nAvailable values:\n\n* `a string`, e.g. `\"database\"`,\n* `a string which is separated by a comma`, e.g. `\"database, siteUrl\"`.\n\n## Use cases\n\n### Complete process for comparison\n\nThis example will show how to compare your production data with data from a backup.\n\n1\\. Restore your backup to a temporary instance. For example you have a backup from `2025-01-01 01:00:00`.\n\n2\\. Install the [Export Import](https://github.com/espocrm/ext-export-import/releases) extension.\n\n3\\. Run the export command to create a dump of your previous data:\n\n```bash\nbin/command export-import export --format=json --path=\"./data/export-import\"\n```\n\n4\\. Install the [Export Import](https://github.com/espocrm/ext-export-import/releases) extension on your production instance.\n\n5\\. Copy the exported data from the step 3 to your production server.\n\n6\\. Run the comparison command on your production instance:\n\n```bash\nbin/command export-import compare --format=json --path=\"./data/backup-data/export-import\" --result-path=\"./data/export-import-result\" --compare-type=all --from-date=\"2025-01-01 01:00:00\" --pretty-print --info\n```\n\n* `--from-date` - the date and time in UTC from which the comparison will be made.\n\n7\\. Check the result in the `./data/export-import-result` directory. See [Result](#result) section.\n\n### Restoring data\n\n!!! note\n\n    Before you start this process, make sure that you have a backup of your production data.\n\n!!! tip\n\n    It is recommended to restore only specified entities.\n\n1\\. Follow the 1-5 steps described in [Complete process for comparison](#complete-process-for-comparison) section.\n\n2\\. Run the comparison command on your production instance:\n\n```bash\nbin/command export-import compare --format=json --path=\"./data/backup-data/export-import\" --result-path=\"./data/export-import-result\" --compare-type=updated --from-date=\"2025-01-01 01:00:00\" --pretty-print --info  --entity-list=\"Account, Contact\" --skip-related-entities\n```\n\n3\\. If the comparison result is OK, then you can import the data to your production instance:\n\n```bash\nbin/command export-import import --format=json --path=\"./data/export-import-result/changed/prev\" --import-type=update\n```\n\n### Compare data when modifiedAt is changed daily by a workflow\n\nFor understanding how to compare data, see [Complete process for comparison](#complete-process-for-comparison) section.\n\n```bash\nbin/command export-import compare --format=json --path=\"./data/export-import\" --result-path=\"./data/export-import-result\" --compare-type=all --from-date=\"2025-01-01 01:00:00\" --pretty-print --info --skip-modified-at\n```\n\n### Compare data when an attribute is changed daily by a workflow\n\nFor understanding how to compare data, see [Complete process for comparison](#complete-process-for-comparison) section.\n\n```bash\nbin/command export-import compare --format=json --path=\"./data/export-import\" --result-path=\"./data/export-import-result\" --compare-type=all --from-date=\"2025-01-01 01:00:00\" --pretty-print --info --skip-modified-at --skip-attribute-list=\"Lead.cAge\"\n```\n"
  },
  {
    "path": "docs/extensions/export-import/customization.md",
    "content": "# Customization\n\nSome additional features can be configured in the metadata defs. The path is `custom/Espo/Custom/Resources/metadata/exportImportDefs`.\n\n## Export additional fields\n\nIf need to export additional fields that out of the standard functionality.\n\n#### exportAdditionalFieldList\n\nExample for Quotes: `custom/Espo/Custom/Resources/metadata/exportImportDefs/Quote.json`\n\n```json\n{\n    \"exportAdditionalFieldList\": [\n        \"itemList\"\n    ]\n}\n```\n\n## Skip export list\n\nIf need to skip some records like `system` user or others.\n\n#### exportSkipLists\n\nExample for User: `custom/Espo/Custom/Resources/metadata/exportImportDefs/User.json`\n\n```json\n{\n    \"exportSkipLists\" : {\n        \"id\": [\n            \"system\"\n        ],\n        \"userName\": [\n            \"tester\"\n        ]\n    }\n}\n```\n\n## Placeholders\n\nEdit the file: `custom/Espo/Custom/Resources/metadata/exportImportDefs/ENTITY.json`.\n\n### Config\n\n#### Get\n\n```json\n{\n    \"fields\": {\n        \"amountCurrency\": {\n            \"placeholderAction\": \"Config\\\\Get\",\n            \"placeholderData\": {\n                \"key\": \"defaultCurrency\",\n                \"default\": null\n            }\n        }\n    }\n}\n```\n\n### User\n\n#### Password\n\n```json\n{\n    \"fields\": {\n        \"password\": {\n            \"placeholderAction\": \"User\\\\Password\",\n            \"placeholderData\": {\n                \"value\": \"1\"\n            }\n        }\n    }\n}\n```\n\n#### Active\n\n```json\n{\n    \"fields\": {\n        \"isActive\": {\n            \"placeholderAction\": \"User\\\\Active\"\n        }\n    }\n}\n```\n\n### Datetime\n\n#### Now\n\n```json\n{\n    \"fields\": {\n        \"dateStart\": {\n            \"placeholderAction\": \"DateTime\\\\Now\"\n        }\n    }\n}\n```\n\n#### ExportDifference\n\nThe difference between the record date and the export date.\nE.g. record date = `2025-05-01`, export date = `2025-08-01`. When import data at `2025-12-01`, the record data will be `2025-09-01`.\n\n```json\n{\n    \"fields\": {\n        \"dateStart\": {\n            \"placeholderAction\": \"DateTime\\\\ExportDifference\"\n        }\n    }\n}\n```\n\n#### ExportDifferenceField\n\nThe same logic as `ExportDifference`, but the initial value gets from another field.\n\n```json\n{\n    \"fields\": {\n        \"createdAt\": {\n            \"placeholderAction\": \"DateTime\\\\ExportDifferenceField\",\n            \"placeholderData\": {\n                \"field\": \"dateStart\",\n                \"defaultAction\": \"DateTime\\\\Now\"\n            }\n        }\n    }\n}\n```\n\nTo get the initial value from a couple fields. The value will be obtained from the first defined field.\n\n```json\n{\n    \"fields\": {\n        \"createdAt\": {\n            \"placeholderAction\": \"DateTime\\\\ExportDifferenceField\",\n            \"placeholderData\": {\n                \"fieldList\": [\n                    \"dateStart\",\n                    \"dateEnd\",\n                    \"dateCompleted\"\n                ],\n                \"default\": \"2026-01-01 01:00:00\"\n            }\n        }\n    }\n}\n```\n\nThe `placeholderData` parameter accepts the following options:\n\n- `field` – Specifies the field name from which to retrieve the value. Note: `field` and `fieldList` are mutually exclusive.\n- `fieldList` – An array of field names to check for a value. The first non-empty field will be used.\n- `default` – A fallback value to use when the specified field(s) contain no data. Note: `default` and `defaultAction` are mutually exclusive.\n- `defaultAction` – A fallback placeholder action to execute when the specified field(s) contain no data.\n\n#### CurrentMonth\n\n```json\n{\n    \"fields\": {\n        \"dateStart\": {\n            \"placeholderAction\": \"DateTime\\\\CurrentMonth\"\n        }\n    }\n}\n```\n\n#### CurrentYear\n\n```json\n{\n    \"fields\": {\n        \"dateStart\": {\n            \"placeholderAction\": \"DateTime\\\\CurrentYear\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "docs/extensions/export-import/export.md",
    "content": "# Export\n\nThe export feature is available in the [Export Import](https://github.com/espocrm/ext-export-import/releases) extension.\n\n## Usage\n\nThis extension works via console (CLI). Commands should be executed from the `root directory` of your EspoCRM instance.\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\"\n```\n\n## Available options\n\n#### `--y`\n\nConfirmation of running the import. By default, a prompt will be displayed.\n\n#### `--path`\n\nAn export path. The default value is `./data/export-import`. Example: `--path=\"PATH\"`.\n\n#### `--skip-data`\n\nSkip exporting data. By default, all data will be exported / imported.\n\n#### `--skip-customization`\n\nSkip exporting all customization made for the instance. By default, all customization will be exported.\n\n#### `--skip-config`\n\nSkip exporting configuration data. By default, all configuration data will be exported.\n\n#### `--skip-internal-config`\n\nSkip exporting internal configuration data which are stored at `config-internal.php`.\nUse [`--user-password`](import.md/#-user-password) in order to set a user password since the `passwordSalt` will not be exported.\n\n#### `--entity-list`\n\n!!! note\n\n    - For advanced users only.\n    - The defined list will be imported only with data of `Many-to-One`, `One-to-One Right`, `Children-to-Parent` relationships.\n    - The `Many-to-Many`, `One-to-Many`, `One-to-One Left`, `Parent-to-Children` relationships for related entities should be defined in the list additionally.\n\nA list of Entity Types. If omitted, then all entity types are applied. Example: `--entity-list=\"ENTITY_TYPE1, ENTITY_TYPE2\"`\n\nSupported values:\n\n* a string, e.g. `\"Account\"`;\n* a string which is separated by a comma, e.g. `\"Account, Contact\"`.\n\n#### `--all-customization`\n\n**Note**: This option works along with the `--entity-list` option only.\n\nThis option enables exporting all customization, ignoring the `--entity-list` option for customization.\n\n#### `--skip-related-entities`\n\nSkip exporting data and customization for related entities. This option is used in conjunction with `--entity-list`. By default, this option is `off`.\n\n#### `--pretty-print`\n\nStore data in a pretty print format. By default this option is `off`.\n\n#### `--user-skip-list`\n\nDefine a list of users to be skipped. The value can be a list of `ID` or `User Name`. Example: `--user-skip-list=\"admin\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"admin\"`,\n* `a string which is separated by a comma`, e.g. `\"admin, 65d34ab18e81e286e\"`.\n\n#### `--skip-password`\n\nSkip exporting passwords and changing passwords for existing users. Example: `--skip-password`.\nUse [`--user-password`](import.md/#-user-password) in order to set a user password.\n\n#### `--from-date`\n\nExport data from a specific date and time. All data before this date will be ignored. Applies only to entities with a `modifiedAt` field.\nThe date should be in UTC and in the format *YYYY-MM-DD HH:mm:ss*.\nBy default, this option is `off`. Example: `--from-date=\"2025-01-01 00:00:00\"`\n\n#### `--entity-skip-list`\n\nThis option allows you to skip exporting data for defined entities. Example: `--entity-skip-list=\"ENTITY_TYPE\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"Account\"`,\n* `a string which is separated by a comma`, e.g. `\"Account, Contact\"`.\n\n#### `--entity-hard-list`\n\nThis option allows you to export data for entities which are disabled by default, in `exportImportDefs` with the `\"exportDisabled\": true` or `\"importDisabled\": true` option. Example: `--entity-hard-list=\"ENTITY_TYPE\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"ScheduledJob\"`,\n* `a string which is separated by a comma`, e.g. `\"ScheduledJob, ScheduledJobLogRecord\"`.\n\n#### `--config-hard-list`\n\nThis option allows you to export data for config options which are disabled by default. Ex. `--config-hard-list=\"CONFIG_OPTION\"`.\nThe default list is defined in `application/Espo/Modules/ExportImport/Resources/metadata/app/exportImport.json`.\n\nAvailable values:\n\n* `a string`, e.g. `\"database\"`,\n* `a string which is separated by a comma`, e.g. `\"database, siteUrl\"`.\n\n## Use cases\n\n### Skip exporting passwords\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --skip-password\n```\n\n### Export customization only\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --skip-data --skip-config\n```\n\n### Export customization for a single entity along with relationships\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --skip-data --skip-config --entity-list=\"Account\"\n```\n\n### Export customization for a single entity without relationships\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --skip-data --skip-config --entity-list=\"Account\" --skip-related-entities\n```\n\n### Export data, configuration, customization for a single entity along with relationships\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"Account\"\n```\n\n### Export data, configuration, customization for a single entity without relationships\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"Account\" --skip-related-entities\n```\n\n## Use cases for Advanced Pack\n\n### Reports\n\n#### Export reports\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"Report, ReportCategory, ReportFilter, ReportPanel\" --skip-config --skip-customization --skip-related-entities\n```\n\n#### Export reports with custom entities\n\nIf the Target Entity of at least one of the reports is a custom entity, you need to add it to the `--entity-list` option. Example:\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"Report, ReportCategory, ReportFilter, ReportPanel, CustomEntity\" --skip-config --skip-customization --skip-related-entities\n```\n\n#### Export reports with custom fields\n\nIf the Target Entities of the reports are default entities, but at least one field in the one report is a custom field, you should add an `--all-customization` option and remove `--skip-customization` option. Example:\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"Report, ReportCategory, ReportFilter, ReportPanel\" --skip-config --all-customization --skip-related-entities\n```\n\n### Workflow\n\nIf there are certain actions in the workflow, it's important to add the following entities to the `--entity-list` option (depending on the workflow actions):\n\n- Send Email - EmailTemplate, User, Team\n- Create Record - custom entity name if it is present in the action\n- Create Related Record - custom entity name if it is present in the action\n- Update Related Record - custom entity name if it is present in the action\n- Link with another Record - custom entity name  if it is present in the action\n- Unlink from another Record - custom entity name  if it is present in the action\n- Apply Assignment Rule - Team, Report\n- Create Notification - User, Team\n- Make Followed - User, Team\n- Start BPM Process - BpmnFlowchart\n\n#### Export workflows\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"Workflow, WorkflowCategory, WorkflowCategoryPath\" --skip-config --skip-customization --skip-related-entities\n```\n\n#### Export workflows created or changed since a specific date\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"Workflow, WorkflowCategory, WorkflowCategoryPath\" --skip-config --skip-customization --skip-related-entities --from-date=\"2025-01-01 00:00:00\"\n```\n\n#### Export workflows with custom entities\n\nIf the Target Entity of at least one of the workflows is custom entity, you need to add it to the `--entity-list` option. Example:\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"Workflow, WorkflowCategory, WorkflowCategoryPath, CustomEntity\" --skip-config --skip-customization --skip-related-entities\n```\n\n### BPM\n\nDepending on the presence of certain BPM elements, the following entities should be added to the `--entity-list` option:\n\n- Task - see [Actions performance for Workflow and BPMs](#workflow)\n- Send Message Task - EmailTemplate, User, Team\n- User Task - Team\n\n#### Export BPMs\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"BpmnFlowchart\" --skip-config --skip-customization --skip-related-entities\n```\n\n#### Export BPMs with custom entities\n\nIf the Target Entity of at least one of the BPMs is custom entity, you need to add it to the `--entity-list` option. Example:\n\n```\nbin/command export-import export --format=json --path=\"./data/export-import\" --entity-list=\"BpmnFlowchart, CustomEntity\" --skip-config --skip-customization --skip-related-entities\n```\n"
  },
  {
    "path": "docs/extensions/export-import/import.md",
    "content": "# Import\n\nThe import feature is available in the [Export Import](https://github.com/espocrm/ext-export-import/releases) extension.\n\n## Usage\n\nThis extension works via console (CLI). Commands should be executed from the `root directory` of your EspoCRM instance.\n\n```\nbin/command export-import import --format=json --path=\"./data/export-import\" --import-type=createAndUpdate\n```\n\n## Available options\n\n#### `--y`\n\nConfirmation of running the import. By default, a prompt will be displayed.\n\n#### `--path`\n\nAn import path. The default value is `./data/export-import`. Example: `--path=\"PATH\"`.\n\n#### `--skip-data`\n\nSkip importing data. By default, all data will be imported.\n\n#### `--skip-customization`\n\nSkip importing all customization made for the instance. By default, all customization will be imported.\n\n#### `--skip-config`\n\nSkip importing configuration data. By default, all configuration data will be imported.\n\n#### `--skip-internal-config`\n\nSkip importing internal configuration data which are stored at `config-internal.php`.\nUse [`--user-password`](#-user-password) in order to set a user password since the `passwordSalt` will not be imported.\n\n#### `--entity-list`\n\n!!! note\n\n    - For advanced users only.\n    - The defined list will be imported only with data of `Many-to-One`, `One-to-One Right`, `Children-to-Parent` relationships.\n    - The `Many-to-Many`, `One-to-Many`, `One-to-One Left`, `Parent-to-Children` relationships for related entities should be defined in the list additionally.\n\nA list of Entity Types. If omitted, then all entity types are applied. Example: `--entity-list=\"ENTITY_TYPE1, ENTITY_TYPE2\"`\n\nSupported values:\n\n* a string, e.g. `\"Account\"`;\n* a string which is separated by a comma, e.g. `\"Account, Contact\"`.\n\n#### `--all-customization`\n\n**Note**: This option works along with the `--entity-list` option only.\n\nThis option enables importing all customization, ignoring the `--entity-list` option for customization.\n\n#### `--skip-related-entities`\n\nSkip importing data and customization for related entities. This option is used in conjunction with `--entity-list`. By default, this option is `off`.\n\n#### `--import-type`\n\nAn import type. The default value is `createAndUpdate`. Example: `--import-type=\"TYPE\"`.\n\nAvailable values:\n\n* `create`\n* `createAndUpdate`\n* `update`\n\n#### `--activate-users`\n\nActivate all imported users. The `Is Active` option will be defined as `true`.\n\n#### `--deactivate-users`\n\nDeactivate all imported users. The `Is Active` option will be defined as false.\nIn order to keep at least one active user, use `--user-active-list=\"admin\"`.\n\n#### `--user-active-list`\n\nDefine a list of active users. The value can be a list of `ID` or `User Name`. Other users will be deactivated. Example: `--user-active-list=\"admin\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"admin\"`,\n* `a string which is separated by a comma`, e.g. `\"admin, 65d34ab18e81e286e\"`.\n\n#### `--user-skip-list`\n\nDefine a list of users to be skipped. The value can be a list of `ID` or `User Name`. Example: `--user-skip-list=\"admin\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"admin\"`,\n* `a string which is separated by a comma`, e.g. `\"admin, 65d34ab18e81e286e\"`.\n\n#### `--user-password`\n\nA user password for all imported users. Example: `--user-password=\"PASSWORD\"`.\n\nFor resetting the password, use `bin/command set-password [username]`.\n\n#### `--skip-password`\n\nSkip changing passwords for existing users. Example: `--skip-password`.\nUse [`--user-password`](#-user-password) in order to set a user password.\n\n#### `--update-currency`\n\nTo update all currency fields. This option depends on [`currency`](#-currency). If the `currency` option is not defined, the default currency will be used instead. By default, this option is `off`.\n\n#### `--currency`\n\nCurrency symbol. If not defined, the default currency will be used instead. Example: `--currency=\"USD\"`.\n\n#### `--update-created-at`\n\nCurrent time for the `createdAt` field. By default, this option is `off`.\n\n#### `--entity-skip-list`\n\nThis option allows you to skip importing data for defined entities. Example: `--entity-skip-list=\"ENTITY_TYPE\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"Account\"`,\n* `a string which is separated by a comma`, e.g. `\"Account, Contact\"`.\n\n#### `--entity-hard-list`\n\nThis option allows you to import data for entities which are disabled by default, in `exportImportDefs` with the `\"exportDisabled\": true` or `\"importDisabled\": true` option. Example: `--entity-hard-list=\"ENTITY_TYPE\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"ScheduledJob\"`,\n* `a string which is separated by a comma`, e.g. `\"ScheduledJob, ScheduledJobLogRecord\"`.\n\n#### `--config-hard-list`\n\nThis option allows you to import data for config options which are disabled by default. Ex. `--config-hard-list=\"CONFIG_OPTION\"`.\nThe default list is defined in `application/Espo/Modules/ExportImport/Resources/metadata/app/exportImport.json`.\n\nAvailable values:\n\n* `a string`, e.g. `\"database\"`,\n* `a string which is separated by a comma`, e.g. `\"database, siteUrl\"`.\n\n#### `--entity-import-type-create`\n\nThis option allows you to define a custom `create` import type for specified entity types. Example: `--entity-import-type-create=\"ENTITY_TYPE\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"User\"`,\n* `a string which is separated by a comma`, e.g. `\"Account, Contact\"`.\n\n#### `--entity-import-type-update`\n\nThis option allows you to define a custom `update` import type for specified entity types. Example: `--entity-import-type-update=\"ENTITY_TYPE\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"User\"`,\n* `a string which is separated by a comma`, e.g. `\"Account, Contact\"`.\n\n#### `--entity-import-type-create-and-update`\n\nThis option allows you to define a custom `createAndUpdate` import type for specified entity types. Example: `--entity-import-type-create-and-update=\"ENTITY_TYPE\"`.\n\nAvailable values:\n\n* `a string`, e.g. `\"User\"`,\n* `a string which is separated by a comma`, e.g. `\"Account, Contact\"`.\n\n## Use cases\n\n### Keep passwords for existing users\n\n```\nbin/command export-import import --format=json --path=\"./data/export-import\" --skip-internal-config --skip-password\n```\n\n### Import customization only\n\n```\nbin/command export-import import --format=json --path=\"./data/export-import\" --skip-data --skip-config\n```\n\n### Import customization for a single entity along with relationships\n\n```\nbin/command export-import import --format=json --path=\"./data/export-import\" --skip-data --skip-config --entity-list=\"Account\"\n```\n\n### Import customization for a single entity without relationships\n\n```\nbin/command export-import import --format=json --path=\"./data/export-import\" --skip-data --skip-config --entity-list=\"Account\" --skip-related-entities\n```\n\n### Import data, configuration, customization for a single entity along with relationships\n\n```\nbin/command export-import import --format=json --path=\"./data/export-import\" --import-type=createAndUpdate --entity-list=\"Account\"\n```\n\n### Import data, configuration, customization for a single entity without relationships\n\n```\nbin/command export-import import --format=json --path=\"./data/export-import\" --import-type=createAndUpdate --entity-list=\"Account\" --skip-related-entities\n```\n"
  },
  {
    "path": "docs/extensions/export-import/overview.md",
    "content": "# Export Import extension\n\nThe Export Import extension is a tool for transferring data between EspoCRM instances using CLI commands.\n\nWhat can be transferred:\n\n* records\n* settings\n* customizations\n* files\n\nHow it can be used:\n\n* as a part of a continuous delivery pipeline (e.g. to transfer roles, workflows, BPM flowcharts from dev to production);\n* for demo data;\n* when migrating to another instance;\n* to track changes;\n* to restore updated or deleted records.\n\n## Installing\n\nYou need to install the Export Import extension on your EspoCRM instance. Download the latest release package from the [GitHub repository](https://github.com/espocrm/ext-export-import/releases). Follow [instructions](https://docs.espocrm.com/administration/extensions/#installing) to install the extension.\n\n## Features\n\n* [Export](export.md)\n* [Import](import.md)\n* [Compare changes](compare.md)\n\n## Additional information\n\n* [Run by code](run-by-code.md)\n* [Customization](customization.md)\n"
  },
  {
    "path": "docs/extensions/export-import/run-by-code.md",
    "content": "# Run by code\n\nIn addition to the CLI, the commands can be executed by a code.\n\n## Import\n\nThe `ExportImport` service can be injected as a constructor parameter.\n\n```php\nnamespace Espo\\Custom\\Tools;\n\nuse Espo\\Modules\\ExportImport\\Tools\\ExportImport;\n\nclass MyImportTest\n{\n    public function __construct(private ExportImport $exportImportTool)\n    {}\n\n    public function runImport()\n    {\n        $this->exportImportTool->runImport([\n            'path' => 'custom/Espo/Custom/MyData',\n            'skipInternalConfig' => true,\n            'userPassword' => 1,\n            'userActiveList' => [\n                'admin'\n            ],\n            'updateCurrency' => true,\n            'updateCreatedAt' => true,\n            'entityHardList' => [\n                'ScheduledJob'\n            ],\n        ]);\n    }\n}\n```\n\n## Export\n\nTo export data, you can use the `runExport` method of the `ExportImport` service.\n\n```php\nnamespace Espo\\Custom\\Tools;\n\nuse Espo\\Modules\\ExportImport\\Tools\\ExportImport;\n\nclass MyExportTest\n{\n    public function __construct(private ExportImport $exportImportTool)\n    {}\n\n    public function runExport()\n    {\n        $this->exportImportTool->runExport([\n            'path' => 'custom/Espo/Custom/MyData',\n            'entityList' => ['Account', 'Contact'],\n            'skipConfig' => true,\n            'skipCustomization' => true,\n            'skipRelatedEntities' => true,\n        ]);\n    }\n}\n```\n"
  },
  {
    "path": "docs/extensions/google-integration/calendar.md",
    "content": "# Google Integration. Calendar sync\n\n!!! note\n\n    Before proceeding to this article, it's recommended to [set up the integration](setting-up.md).\n\n[Google Integration](https://www.espocrm.com/extensions/google-integration) provides the ability to sync calendar events in both directions.\n\nFeatures:\n\n* The ability to monitor multiple calendars.\n* Syncing since specified date.\n* Syncing attendees.\n* The ability to choose what event types to sync.\n* Private events are not synced.\n\n## Setting-up for users\n\nAssuming that the administrator has already set up the integration.\n\nGo to your user detail view (the menu on the very top-right corner > click on your user name). Then click *External Account* button.\n\n![External account button](../../_static/images/extensions/google-integration/external-account-button.png)\n\nClick *Google* on the left panel, check *Enabled* checkbox and then click *Connect* button.\n\n![Connect](../../_static/images/extensions/google-integration/connect.png)\n\nA popup will show up asking for a user consent.\n\nIf everything went fine, a green label *Connected* should show up.\n\n!!! important\n\n    If you connected successfully, but *Google Calendar* checkbox didn't show up, that means that the administrator did not grant you access to *Google Calendar* scope.\n\nCheck *Google Calendar* checkbox and configure sync parameters.\n\nAfter that, you need to click *Save*.\n\n![Params](../../_static/images/extensions/google-integration/calendar-params.png)\n\n## Parameters\n\n* Direction – a type of sync. Possible types: *One-way: EspoCRM to Google*, *One-way: Google to EspoCRM*, and *Two-way*.\n\n* Sync since – events created or modified after a specified date will be synced.\n\n* Sync Entities and Identification Labels – types of entities you want to sync. For type recognizing, the event name has to start from the identification label. Label for default entity can be empty. Recommendation: Do not change identification labels after the sync has already happened.\n\n* Default Entity – by default, events will be synced as entities of a selected type.\n\n* Remove Google Calendar Event upon removal in EspoCRM – if you create an event in Google Calendar, you can not delete it from EspoCRM (if you delete it in CRM, this event won’t be deleted in Google Calendar). If you check this box, it will allow to delete Google event from EspoCRM as well.\n\n* Don’t sync event attendees.\n\n* Main Calendar – all new events from EspoCRM will be created in this calendar (actual for *One-way: EspoCRM to Google* or *Two-way*).\n\n* Other Calendars – other calendars to monitor.\n\n* Assign User's Default Team - a user default team will be auto-assigned to an event synced from Google Calendar to EspoCRM (see the `Default Team` parameter in a user's profile).\n\n## Misc\n\nIf your Espo entity type has a  *Varchar* or *Text* field named `location`,  it will be synced with the Google Calendar's location.\n"
  },
  {
    "path": "docs/extensions/google-integration/contacts.md",
    "content": "# Google Integration. Contacts\n\n!!! note\n\n    Before proceeding to this article it's recommended to [set up the integration](setting-up.md).\n\nFeatures:\n\n* The ability to push your EspoCRM contacts and leads to Google Contacts;\n* The ability to choose Google Contacts groups;\n* Fields pushed: *Name*, *Description*, *Email Addresses*, *Phone Numbers*, *Account Name*, *Account Title*, *Address*.\n\n## Setting-up for users\n\nAssuming that the administrator has already set up the integration.\n\nGo to your user detail view (the menu on the very top-right corner > click on your user name). Then, click *External Account* button.\n\n![External account button](../../_static/images/extensions/google-integration/external-account-button.png)\n\nClick *Google* on the left panel, check *Enabled* checkbox and then click *Connect* button.\n\n![Connect](../../_static/images/extensions/google-integration/connect.png)\n\nA popup will show up asking for a user consent.\n\nIf everything went fine, a green label *Connected* should show up.\n\n!!! important\n\n    If you connected successfully, but *Google Contacts* checkbox didn't show up, that means that the administrator did not grant you access to *Google Contacts* scope.\n\nCheck *Google Calendar* checkbox. You can select *Google Contacts Groups*, to which EspoCRM records will be pushed.\n\nAfter that, you need to click *Save*.\n\n## Pushing to Google\n\nGo to Contacts or Leads list view, select needed items, then click *Actions* dropdown and click *Push to Google*.\n\nA single portion can contain up to 10 records. The rest will be pushed in idle mode (by cron).\n\n![Push to Google](../../_static/images/extensions/google-integration/push-to-google.png)\n\nAfter that, you can find your contacts in Google.\n"
  },
  {
    "path": "docs/extensions/google-integration/gmail.md",
    "content": "# Google Integration. Gmail\n\n!!! note\n\n    Before proceeding to this article it's recommended to [set up the integration](setting-up.md).\n\nGmail Secure Authentication is available in [Google Integration](https://www.espocrm.com/extensions/google-integration) extension. It provides a secure authentication for Gmail accounts via OAuth2. With this extension, you won’t need to store your Gmail password in EspoCRM and enable access for less secure applications in your Google Account settings.\n\n## Setting-up email account\n\nAssuming that the administrator has already set up the integration.\n\nCreate a personal or group email account. Specify IMAP and SMTP parameters for Gmail (hosts: `imap.gmail.com` & `smtp.gmail.com`). Leave *Password* fields empty. Then, save the record.\n\nAfter that, *Gmail* panel should appear on the right. You need to click *Connect* button. A popup will show up asking for a user consent.\n\n!!! note\n\n    You need to be logged in to Google as a user to which an email address of the current email account record belongs. For example, if you configure email account for *example@gmail.com*, you need to log in to Google as a user who has *example@gmail.com* email address.\n\n![Panel](../../_static/images/extensions/google-integration/gmail.png)\n\nAfter that, you can test imap connection and sent test email to make sure everything works fine.\n\n### Using only IMAP or only SMTP\n\nOnce you connect the email account to Google, it will use authentication to Google for both IMAP and SMTP. If you want to use the Google authentication only for IMAP or only for SMTP, while using a different host for another protocol, you need to create a separate email account (for the same user and the same email address).\n"
  },
  {
    "path": "docs/extensions/google-integration/setting-up.md",
    "content": "# Google Integration. Setting-up for Administrator\n\nNote that the integration requires curl, libxml and xml PHP extensions installed. If any is not installed, you will be notified after saving.\n\n* [Integration](#integration)\n* [Access control](#access-control)\n\n## Integration\n\nGo to the Administration > Integrations > Google. Check *Enabled* checkbox.\n\n* You will obtain *Client ID* and *Client Secret* in Google Developers Console.\n* You will need to copy *Redirect URI*  to Google Developers Console.\n\n![Integration](../../_static/images/extensions/google-integration/setting-up/1.png)\n\nDo the following steps.\n\n**1\\.** Go to the [Google Developers Console](https://console.developers.google.com/).\n\n**2\\.** Create a new project, or select an existing one.\n\n**3\\.** Enable needed APIs.\n\nFrom the Navigation menu, click *APIs & Services* > *Enabled APIs & services*.\n\n![APIs and Services](../../_static/images/extensions/google-integration/setting-up/3.png)\n\nThen, click *+ ENABLE APIS AND SERVICES*.\n\n![Enable APIs and Services](../../_static/images/extensions/google-integration/setting-up/3a.png)\n\nOn the API Library page, use search to find the relevant APIs:\n\n* Google Calendar API (for Calendar sync);\n* Google People API (for Contacts pushing);\n* Gmail API (for secure connection to Gmail).\n\nEnable the APIs that you need to use in your CRM. Note that some APIs can be already enabled.\n\n![Enable API](../../_static/images/extensions/google-integration/setting-up/3b.png)\n\n**4\\.** Configure consent screen.\n\nTo create an OAuth client ID, you must first configure your OAuth consent screen. Go to OAuth consent screen and follow the instructions on the page.\n\n![Enable API](../../_static/images/extensions/google-integration/setting-up/4.png)\n\n**5\\.** Create credentials.\n\nOn the *Credentials* page, click *CREATE CREDENTIALS*, select *OAuth client ID*.\n\n![Credentials](../../_static/images/extensions/google-integration/setting-up/5.png)\n\nSelect 'Web application' in *Application type* field. Add your site URL in *Authorized JavaScript origins*. Add *Redirect URI* (copied from EspoCRM integration panel) to *Authorized redirect URIs*.\n\n![Client ID](../../_static/images/extensions/google-integration/setting-up/5a.png)\n\n**6\\.** Find *Client ID* and *Client secret*. Copy them to EspoCRM integration panel and save.\n\n!!! note\n\n    The Site URL should be configured properly in EspoCRM – it should be the URL address used to access your CRM instance. Otherwise, the integration will not work. The parameter is available under: Administration > Settings > Site URL.\n\n## Access control\n\n**Important**: By default, regular users don’t have access to Google Calendar and Contacts integrations. Administrator needs to enable access in Roles. The following scopes need to be enabled:\n\n* External Accounts;\n* Google Calendar;\n* Google Contacts.\n\n![Roles](../../_static/images/extensions/google-integration/setting-up/roles.png)\n"
  },
  {
    "path": "docs/extensions/meeting-scheduler/index.md",
    "content": "# Meeting Scheduler\n\n*Requires EspoCRM v9.0.*\n\nAvailable in the [Meeting Scheduler](https://www.espocrm.com/extensions/meeting-scheduler/) extension.\n\nWith the Meeting Scheduler tool you can create online pages where contacts can book meetings with CRM users. Contacts can choose from time slots when the host is available. The scheduler configuration can help avoid meeting overload. You can also set up automated meeting distribution among multiple hosts.\n\nIn this article:\n\n* [Access](#access)\n* [General](#general)\n* [Setting up](#setting-up)\n* [Overrides](#overrides)\n* [Questions](#questions)\n* [One-time links](#one-time-links)\n* [Requests](#requests)\n* [Round-robin host distribution](#round-robin-host-distribution)\n* [Zoom integration](#zoom-integration)\n* [Microsoft Teams integration](#microsoft-teams-integration)\n\nSee more:\n\n* [Quick tour](https://app.supademo.com/demo/cmk18ly211ylwgmn8ctdsigqr)\n\n## Access\n\nAccess to Meeting Schedulers and Meeting Requests are controlled by roles.\n\nAn administrator can allow regular users to create and edit scheduler pages by setting needed access levels for the Meeting Scheduler scope.\n\nThere's a possible configuration where a Meeting Scheduler is managed by one user but requests are distributed to other users. To be able to access Meeting Requests where the user is a host, the user should have the Meeting Scheduler scope enabled. Setting the action levels for the scope is not required – they all can be set to 'no'.\n\nThe Meeting Scheduler Hosts scope allows users to configure schedulers that distribute meetings to other users.\n\n## General\n\nThe system uses the parameter *Free/Busy Entity List* when determining busy time slots. This parameter is available under: Administration > Settings.\n\n!!! note\n\n    An attendee is required to fill in the email address when booking a meeting.\n\n## Setting up\n\nYou can access the Meeting Schedulers list view from the navbar. There, you can create a new Meeting Scheduler.\n\nIt's also possible to access Meeting Schedulers from the Meeting's list view.\n\n### General\n\n#### Name\n\nThe name field will be used for meeting names and for the page title of the scheduling page.\n\n#### Active\n\nIf a scheduler is not set as Active, the scheduling page will be unaccessible.\n\n#### Date Start, Date End\n\nThe Date Start and Date End fields allow to set a period during which the scheduling page is functional.\n\n#### Description\n\nThe description does not play any role other than of a description text for a user who view the scheduler.\n\n### Setup\n\n#### Meeting durations\n\nSpecify meeting duration options an invitee can pick from.\n\n#### Meeting time precision\n\nThe granularity of time slots available for scheduling meetings.\n\n#### Buffer time before meeting\n\nThe amount of time automatically reserved before a meeting starts to prevent back-to-back scheduling.\n\n#### Buffer time after meeting\n\nThe amount of time automatically reserved after a meeting ends to prevent back-to-back scheduling.\n\n#### Minimum lead time before meeting\n\nThe shortest amount of time that must pass between the moment a meeting is scheduled and its start time.\n\n#### Scheduling window\n\nHow far in the future a meeting can be scheduled.\n\n#### Daily limit\n\n*As of v1.1.*\n\nMaximum number of meetings that can be scheduled in a day. If more than the specified number are scheduled via the form, the day will be excluded from availability.\n\n#### Require approval by host\n\nA meeting won't be created until the request is approved by the host. The primary host can approve requests.\n\n#### Do not require approval if Contact exists\n\nIf a meeting request is created by an invitee that already exists in the CRM as a Contact, then the approval step will be skipped. The email address is used to find a matching Contact.\n\n#### Do not reserve if unapproved\n\nIf checked, then while a request is created but still is unapproved, it won't affect the host's availability. Multiple requests on the same time slots are possible in this case.\n\n#### Require confirmation by invitee\n\nA meeting won't be created until the request is confirmed by the invitee. The invitee will receive an email asking for confirmation. They can also cancel the request from the email.\n\n#### Do not require approval if Contact exists\n\nIf a meeting request is created by an invitee that already exists in the CRM as a Contact, then the confirmation step will be skipped. The email address is used to find a matching Contact.\n\n#### Do not reserve if unconfirmed\n\nIf checked, then while a request is created but still is unconfirmed, it won't affect the host's availability. Multiple requests on the same time slots are possible in this case.\n\n#### Confirmation window\n\nA period during which the invitee can confirm the request. After its expiration, the request will be marked as Expired.\n\n#### Send email invitation\n\nIf checked, then an email invitation will be sent to the invitee upon meeting creation. The email invitations functionality is an out-of-the-box feature of EspoCRM. The email template can be configured under Administration > Template Manager > Invitation · Meeting.\n\nThe invitee can accept or decline the meeting from the invitation email.\n\n#### Online location\n\nSpecify the external service that will be used for online meetings. See below about the Zoom integration.\n\n#### Forbid free email domains\n\nIf checked, an invitee won't be able to specify an email address of free email providers. Such as gmail.com, outlook.com, etc. They will be asked to use their work email address.\n\n#### Blocklists\n\nSelected Target Lists will be used as blocklists. If an invitee uses an email address that matches the email address of any target of the selected Target List, they won't be able to create a request.\n\n#### Meeting Description\n\nThe description text that will be added to the meeting record.\n\n### Schedule\n\nHere you need to specify the availability schedule.\n\nThe *Schedule* field defines time ranges of the general day schedule. Below, specify available weekdays. For each weekday, it's possible to define a custom day schedule. For example, on Friday you can have a shorter working day.\n\nThe *Time Zone* defines the time zone of the configured schedule. Only this time zone is taken into account for the availability schedule. The user's time zone and the system default time zone have no effect here.\n\n#### Consider working time\n\nIf checked, the working time of a host will be taken into account in their availability. For example, if a host is on day-off, they won't be available in the scheduler.\n\nThe Working Time Calendar is the out-of-the-box feature in EspoCRM.\n\nNote that it's possible to override the availability schedule for specific day ranges and for specific hosts. See below about overrides.\n\n### Form\n\nHere you configure the scheduling page (form). The form URL will be generated after the Meeting Scheduler record is created. You can also re-generate the form URL. After re-generating, the form won't be accessible by the previous URL.\n\n#### Language used on form\n\nChoose the language that will be used on the scheduling form. You can edit labels for the needed language under Administration > Label Manager > Meeting Scheduler, Meeting Request.\n\n#### Allowed hosts for form embedding\n\nIt's possible to include the scheduling form in an inline frame element (iframe) on a website. You need to specify the host of the website you are going to include the form on.\n\n#### Form Captcha\n\nEnables reCAPTCHA for the form. To be able to use Captcha, you need to configure it under Administration > Integrations.\n\n#### Text to display on form\n\nThe text will be displayed on the scheduling page at the top.\n\n#### URL to redirect to after form submission\n\nIf specified, once an invitee submits the form, they will be redirected to the specified URL.\n\nThe `meetingSchedulerRequest` URI parameter with the request ID will be appended to the URL. This allows you to retrieve the request data (for software developers).\n\n#### Text to display after form submission\n\nThe text that will be displayed to an invitee once they submitted the form.\n\n#### Enable Form URL\n\nIf not checked, the form won't be accessible by the form URL.\n\n### Hosts\n\nHere you can specify hosts and configure their distribution.\n\nIf no hosts are specified, then meetings will be assigned to the assigned user of the Meeting Scheduler record.\n\nOnly users who have the Meeting Scheduler Hosts scope enabled in their roles can edit the Hosts section.\n\nMore information about host distribution is available in the Round-Robin section below.\n\n#### Fixed hosts\n\nDesignate hosts that should always attend a meeting. If at least one of the fixed hosts is not available at a specific time, it won't be possible to schedule a meeting then.\n\nOne of the fixed hosts is designated as primary. Meetings will be assigned to the primary host.\n\nIt's possible to have no fixed hosts.\n\n#### Rotating hosts\n\nRotating hosts are automatically picked by a specific round-robin algorithm. If at least one rotating host is available at a specific time, the time slot is treated as available for scheduling.\n\n#### Number of rotating hosts per meeting\n\nIt's possible to have multiple rotating hosts picked per meeting. A meeting cannot be scheduled if the number of available hosts is fewer than the specified number.\n\nIf the value is not specified, it's treated as one – only one rotating host will be picked.\n\n## Overrides\n\nOverrides allow to change scheduling for a specific date period. There are two types of overrides: *Not Available* and *Available*.\n\nAn override can be associate with a specific user (host). If the host is not specified, the override is applied to the entire scheduler.\n\n## Questions\n\nBy default, there are two mandatory fields on the scheduling form: *Name* and *Email Address*. It's possible to add additional custom question.\n\nAvailable field types:\n\n* String\n* Text\n* Enum\n* Checkbox\n* Checklist\n* Phone\n* Number\n* Decimal\n\nQuestions can be set as required or optional. It's possible to specify a tooltip text for specific questions. Certain questions can be inactivated.\n\nAn attendee's answers to the questions will be available in the Meeting Request record. They will be also added to the meeting's description.\n\n## One-time links\n\nOne-time links are useful when you don't want to share your main scheduler page to avoid unwanted meetings. You can send a one-time link to a specific customer, allowing them to book a meeting with you.\n\n* Once a link is consumed, it's not available anymore.\n* Optionally, you can set an expiration date and time for a link.\n* A link can be associated with a specific Contact or Lead. In this case the created meeting will be automatically associated with that contact regardless of what email address the attendee specified. On the scheduling form, the email address will be pre-filled with the contact's email address.\n\nNote that one-time links function even if the Form URL is deactivated.\n\n## Requests\n\nOnce an invitee filled in the scheduling form a Meeting Request is created. The request is assigned to the primary host of the meeting. If neither approval nor confirmation are required, the request will be set as Completed. Otherwise, it will be set as Pending.\n\nRequests can be approved and canceled by the request assignee, the scheduler assignee, and users who have edit access to the scheduler.\n\nMeetings requests can be accessed from navbar. The My Meeting Requests dashlet can be added on the dashboard.\n\nUnconfirmed requests expire. The expiry period is defined by the scheduler's configuration.\n\nOn the Meeting Request detail view you can view the attendee's answers to the questions.\n\n## Round-robin host distribution\n\n!!! note\n\n    Host distribution can be configured only by users who have the Meeting Scheduler Hosts scope enabled in their roles.\n\nThere are two distribution methods available:\n\n* Priority-Least-Recent\n* Balanced\n\n### Priority-Least-Recent method\n\nAvailable hosts with the highest priority are picked. Among them, the one that has been scheduled least recently is chosen.\n\nThere are three priority levels for hosts: Low, Medium, and High.\n\nYou can view and edit hosts selection orders by clicking *View Rotating Hosts* next to the *Edit* button.\n\n#### Assignee priority boost\n\nA host assigned to the Contact will receive the priority boost. This value defines the number of priority steps to increase.\n\n### Balanced method\n\nThe available host with the fewest past selections adjusted by weight is chosen.\n\nYou can view and edit hosts' weights and selection numbers by clicking *View Rotating Hosts* next to the *Edit* button.\n\nWeight can be an arbitrary number. A host with a weight of 100 will receive twice as many meetings as a host with a weight of 50.\n\n#### Assignee weight boost\n\nA host assigned to the Contact will receive the specified weight boost.\n\nUse this parameter if you want to give priority to a contact's assignee.\n\n#### Out-runner threshold\n\nHosts that were selected more than the average, exceeding the specified threshold, will be excluded from availability. Weights are taken into account in calculation.\n\nUse this parameter if you don't want having hosts who received substantially more meetings than other hosts.\n\n## Zoom integration\n\nThe Zoom integration is available as a separate [extension](../zoom-integration/index.md).\n\nWith the Zoom integration installed, Zoom is available as an option in the *Online Location* field of a Meeting Scheduler record. To be able to select the Zoom location, users need to have access to the *Zoom Meetings* scope in their roles.\n\nWhen a meeting is created through the scheduler, a Zoom meeting is automatically created in the meeting assignee's Zoom account. The Join URL is stored in the Espo meeting.\n\n## Microsoft Teams integration\n\nThe integration with Microsoft Teams is implemented in the [Outlook Integration](https://www.espocrm.com/extensions/outlook-integration/) extension.\n\nWith the extension installed, the Microsoft is available as an option in the *Online Location* field of a Meeting Scheduler record. To be able to select the Microsoft location, users need to have access to the *Outlook Calendar* scope in their roles. They also need to be connected to Outlook in their External Account settings and to have the Calendar checkbox enabled. Note that the sync direction can be set to any value including *None*.\n\nWhen a meeting is created through the scheduler, a Microsoft meeting is automatically created in the meeting assignee's calendar. The Join URL is stored in the Espo meeting.\n\n"
  },
  {
    "path": "docs/extensions/outlook-integration/calendar.md",
    "content": "# Outlook Integration. Calendar\n\n!!! note\n\n    Before proceeding to this article, it's recommended to [set up the integration](setting-up.md).\n\nOutlook Calendar Sync is available in the [extension](https://www.espocrm.com/extensions/outlook-integration/).\n\nFeatures:\n\n* Meetings, Calls, custom entities of Event type can be synced from Espo to Outlook.\n* Attendees are synced from Outlook to Espo as Contacts, Leads, and Users.\n\nThree modes of sync are supported:\n\n* Outlook to Espo\n* Espo to Outlook\n* Both\n\nLimitations:\n\n* Outlook recurring activities are not synced to Espo.\n* *Description* field is not synced back from Outlook to Espo if an event was created in Espo.\n* *Description* field is not synced back from Espo to Outlook if an event was created in Outlook.\n* Events created in Espo won't be removed in Espo on removal in Outlook. A measure to overcome a bug in Outlook that could cause unwanted event removals.\n\n## Setting up for users\n\nAssuming that the administrator has already set up the integration.\n\nGo to your user detail view (the menu on the very top-right corner > click on your user name). Then, click *External Account* button.\n\n![External account button](../../_static/images/extensions/outlook-integration/external-account-button.png)\n\nClick *Outlook* on the left panel, check *Enabled* checkbox and then click *Connect* button.\n\n![Connect](../../_static/images/extensions/outlook-integration/connect.png)\n\nA popup will show up asking for a user consent.\n\nIf everything went fine, a green label *Connected* should show up.\n\n!!! important\n\n    If you connected successfully, but *Outlook Calendar* checkbox didn't show up, that means that the administrator did not grant you access to *Outlook Calendar* scope.\n\nCheck *Outlook Calendar* checkbox and configure sync parameters.\n\n![Params](../../_static/images/extensions/outlook-integration/calendar-params.png)\n\nAfter that, you need to click *Save*.\n\n## Misc\n\nIf your Espo entity type has a custom *Varchar* field named `location`,  it will be synced with Outlook Calendar. As of v1.4.0.\n"
  },
  {
    "path": "docs/extensions/outlook-integration/contacts.md",
    "content": "# Outlook Integration. Contacts\n\n!!! note\n\n    Before proceeding to this article it's recommended to [set up the integration](setting-up.md).\n\nOutlook Contacts Integration  is available in the [extension](https://www.espocrm.com/extensions/outlook-integration/).\n\nProvides the ability to push EspoCRM contacts and leads to Outlook Contacts (People). The following fields are pushed: First Name, Last Name, Email Address, Phone Number, and Account Name.\n\n* [Setting up for users](#setting-up-for-users)\n* [Pushing to Outlook](#pushing-to-outlook)\n\n## Setting up for users\n\nAssuming that the administrator has already set up the integration.\n\nGo to your user detail view (the menu on the very top-right corner > click on your user name). Then, click *External Account* button.\n\n![External account button](../../_static/images/extensions/outlook-integration/external-account-button.png)\n\nClick *Outlook* on the left panel, check *Enabled* checkbox and then click *Connect* button.\n\n![Connect](../../_static/images/extensions/outlook-integration/connect.png)\n\nA popup will show up asking for a user consent.\n\nIf everything went fine, a green label *Connected* should show up.\n\n!!! important\n\n    If you connected successfully, but *Outlook Contacts* checkbox didn't show up, that means that the administrator did not grant you access to *Outlook Contacts* scope.\n\nCheck *Outlook Contacts* checkbox and configure parameters and then click *Save*.\n\nOptionally, you can select a contact folder. Contacts will be pushed to that folder.\n\n## Pushing to Outlook\n\n1. Go to the contacts or leads list view.\n2. Select needed items. You can also select all search results.\n3. From *Actions* dropdown menu click *Push to Outlook*.\n\nIt's also possible to push from the detail view. The action is available in the dropdown next to *Edit* button.\n"
  },
  {
    "path": "docs/extensions/outlook-integration/email.md",
    "content": "# Outlook Integration. Email\n\n!!! note\n\n    Before proceeding to this article it's recommended to [set up the integration](setting-up.md).\n\nOAuth IMAP and SMTP authentication is available in the [Outlook Integration](https://www.espocrm.com/extensions/outlook-integration) extension. It provides a secure authentication for Microsoft 365 and Outlook.com accounts. With this extension, you won’t need to store your Outlook password in EspoCRM.\n\nOptionally, the extension allows the use of the Microsoft Graph API for sending emails.\n\nIn this article, both Microsoft 365 and Outlook.com will be referred to as *Outlook*.\n\n## Setting-up email account\n\nAssuming that the administrator has already set up the Outlook integration.\n\nCreate a Personal or Group Email Account. The the you create, specify IMAP and SMTP parameters for Outlook. IMAP host: `outlook.office365.com` or `imap-mail.outlook.com`;  SMTP host: `smtp.office365.com`. Leave the *Password* fields empty for both IMAP and SMTP. Then, save the record.\n\nAfter that, the *Outlook* panel should appear on the right. You need to click *Connect* button. A popup will show up asking for a user consent.\n\n!!! note\n\n    You need to be logged in to Outlook as a user to which an email address of the current email account record belongs. For example, if you configure an email account for *example@outlook.com*, you need to log in to Outlook as a user who has *example@outlook.com* email address.\n\nAfter that, you can test IMAP connection and sent a test email to make sure everything works fine.\n\n!!! note\n\n    If during IMAP testing STARTTLS doesn't work, try the SSL/TLS option.\n\n### Using only IMAP or only SMTP\n\nOnce you connect the email account to Microsoft, it will use authentication to Microsoft for both IMAP and SMTP. If you want to use the Microsoft authentication only for IMAP or only for SMTP, while using a different host for another protocol, you need to create a separate email account (for the same user and the same email address).\n\n## Recommendations\n\nRecommendations for setting up an email account if you encounter errors when connecting to SMTP:\n\n1. Ensure you are not signed into `office.com`.\n2. Clear cookies and other site data.\n3. Go to email account and connect to Outlook.\n4. Click Test Connection button, check if successful.\n6. Click Send Test Email button, check if successful.\n\n## Graph API\n\n*As of v1.6.*\n\nRequires EspoCRM v9.1 or greater.\n\n*Mail.Send* API permission should be enabled for the Azure application in the API Permissions tab.  \n\nAn administrator can enable sending emails via Graph API. Under Administration > Integrations > Outlook, check *Send emails via Graph API*.\n\n!!! important\n\n    When the Graph API is enabled for sending, it's not possible to use the same Espo email account record for both sending emails and receiving emails. Separate email accounts for the same email address should be created. One – for sending (via Graph API), another – for receiving (classic IMAP). Then, connect both accounts to Microsoft using the *Connect* button.\n\n!!! note\n\n    We recommended to use the standard SMTP for email sending. Use Graph API only if necessary.\n\n"
  },
  {
    "path": "docs/extensions/outlook-integration/setting-up.md",
    "content": "# Outlook Integration. Setting-up for Administrator\n\n* [Integration](#integration)\n* [Access control](#access-control)\n* [Sync scheduling](#sync-scheduling)\n* [Troubleshooting](#troubleshooting)\n\n## Integration\n\nGo to the Administration > Integrations > Outlook. Check *Enabled* checkbox.\n\n* You will obtain *Client ID* and *Client Secret* in Azure Active Directory admin center.\n* You will need to copy *Redirect URI* to Azure Active Directory admin center.\n* It is recommended to set `select_account` option as an *Authorization Prompt*.\n\n![Integration](../../_static/images/extensions/outlook-integration/setting-up/1.png)\n\n**1\\.** Go to [aad.portal.azure.com](https://aad.portal.azure.com).\n\n**2\\.** Create an application.\n\nFollow Azure Active Directory > App registration > Register an application.\n\n![App registration](../../_static/images/extensions/outlook-integration/setting-up/2.png)\n\nSelect needed *Supported account types*.\n\nCopy *Redirect URI* from EspoCRM. Note, that type should be set to `Web`.\n\n![App registration](../../_static/images/extensions/outlook-integration/setting-up/3.png)\n\n**3\\.** Copy *Application (client) ID* from Azure app to EspoCRM.\n\n![Client ID](../../_static/images/extensions/outlook-integration/setting-up/4.png)\n\n![Client ID](../../_static/images/extensions/outlook-integration/setting-up/5.png)\n\n**4\\.** Create a secret for Azure app. Copy it to EspoCRM.\n\n![Secret](../../_static/images/extensions/outlook-integration/setting-up/6.png)\n\n![Secret](../../_static/images/extensions/outlook-integration/setting-up/7.png)\n\nIf the *Never* option is not available, choose *In 2 years*. In this case you will need to re-generate the secret in 2 years.\n\n![Secret](../../_static/images/extensions/outlook-integration/setting-up/8.png)\n\n![Secret](../../_static/images/extensions/outlook-integration/setting-up/9.png)\n\n**5\\.** Save Outlook integration credentials in EspoCRM.\n\n**6\\.** Grant required permissions for Azure app.\n\n!!! note\n\n    This step is required for Microsoft 365 users. For Outlook.com, it usually works without this step, but it might be needed either.\n\nClick *Api Permissions* on the left panel. Click *Add a permission*. Click *Microsoft Graph*. Click *Delegated permissions*. Then, use search to find the needed permissions and enable them.\n\nPermissions that need to be enabled:\n\n* offline_access – mandatory;\n* Calendars.ReadWrite – optional – for calendar sync;\n* Contacts.ReadWrite – optional – for contacts pushing;\n* IMAP.AccessAsUser.All – optional – for email fetching;\n* SMTP.Send – optional – for email sending.\n\n![Permissions](../../_static/images/extensions/outlook-integration/setting-up/10.png)\n\nAfter adding the above listed API permissions, click Grant Admin Consent for (your organization).\n\n!!! note\n\n    The Site URL should be configured properly in EspoCRM – it should be the URL address used to access your CRM instance. Otherwise, the integration will not work. The parameter is available under: Administration > Settings > Site URL.\n\n## Access control\n\n**Important**: By default, the regular users don’t have access to Outlook Calendar integration. Administrator needs to enable access in Roles. The following scopes need to be enabled:\n\n* External Accounts;\n* Outlook Calendar;\n* Outlook Contacts.\n\n![Roles](../../_static/images/extensions/outlook-integration/setting-up/roles.png)\n\n\n## Sync scheduling\n\nSync is run by the scheduled job *Outlook Calendar Sync*. By default, it is executed every 10 minutes. You can change scheduling at Administration > Scheduled Jobs > Outlook Calendar Sync.\n\n## Troubleshooting\n\nCheck whether the scheduled job is running Administration > Scheduled Jobs > Outlook Calendar Sync > Log.\n\nCheck EspoCRM log at `data/logs` directory. You can also set the [log mode](../../administration/troubleshooting.md#debug-mode) to `DEBUG` level to obtain more info from the log.\n\n## Microsoft 365 configuration\n\n### Enabling SMTP\n\nFor Microsoft 365, you might need to enable SMTP AUTH for specific mailboxes. See how to do it in the [Microsoft documentation](https://docs.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/authenticated-client-smtp-submission#use-the-microsoft-365-admin-center-to-enable-or-disable-smtp-auth-on-specific-mailboxes).\n"
  },
  {
    "path": "docs/extensions/project-management/projects.md",
    "content": "# Projects\n\nThe Projects functionality is available in the [Project Management](https://www.espocrm.com/extensions/project-management/) extension.\n\nIn this article:\n\n* [Projects](#projects)\n* [Boards](#boards)\n* [Access control](#access-control)\n* [Members](#members)\n* [Tasks](#tasks)\n* [Milestones](#milestones)\n* [Groups](#groups)\n* [Plan view](#plan-view)\n* [Board view](#board-view)\n* [Gantt view](#gantt-view)\n* [Project cloning](#project-cloning)\n* [Dashlet](#dashlet)\n* [Shortcut keys](#shortcut-keys)\n\n## Projects\n\nThe Projects list view is available from the Projects tab in the navigation bar. Here you can create a new Project.\n\nA project owner can manage the project team by adding or removing members (Users) and changing their roles in the project.\n\nEach Project has a Stream. It can be used to post information or attach files. Project updates are automatically posted in the Stream.\n\nA Project has Activities and History panels. Meetings, Calls, and Emails can be related to a Project.\n\n### Project categories\n\n*As of v1.4.*\n\nProjects can be organized into categories. Categories follow a hierarchical, tree-like structure.\n\nAccess to categories is controlled by Roles, with the Project Category scope. Only administrators can create or edit categories.\n\n## Boards\n\nA Project Board defines board Stages for a Project. The *Board* field is mandatory in a Project. It can be set only when you create a Project. Multiple Projects can use the same Project Board.\n\nEach Stage is mapped to a specific Status value. Multiple Stages can be mapped to the same status. For example, the *In Progress* and *Review* stages are mapped to the status *Started*.\n\nAvailable statuses:\n\n* Not Started\n* Started\n* Completed\n* Canceled\n* Deferred\n\nA Task in a Project is usually assigned to a specific Stage. When a Stage is changed, the Task's status is automatically changed to a mapped status.\n\nThe *Default* Project Board is available out of the box. You can create new Project Boards. When you create a Project Board, default Stages are automatically added. You can rename the Stages or add new ones.\n\nTo access Boards, go to: Projects list view > top-right menu > Boards.\n\n## Access control\n\nAccess control for Projects is managed by Roles and project-level roles.\n\n### Roles\n\nTo be able to access Projects, a user must have the *Project* scope enabled in Roles. For minimum access, set: create = no, read = own, edit = no, delete = no.\n\nTo be able to create Projects, a user must have *Create* access for the Project scope and *Read* access for the Project Board scope.\n\n### Project-level Roles\n\nA project owner or a user with *Edit* access can manage project members. Each member has a specific project-level Role.\n\nBuilt-in roles:\n\n* Owner – can edit the Project; can manage members; can create and edit Tasks; has access to the Stream of the Project;\n* Editor – can edit the Project; can create and edit Tasks; has access to the Stream of the Project;\n* Member – can view Tasks assigned to them; can move assigned Tasks between Stages; can edit Tasks they own.\n\nThe admin can create custom Project Roles. The Project Roles list view is available at: the Project list view > the dropdown menu in the top-right corner > Roles.\n\nProject Roles allow fine-grained access control.\n\nA Project Role defines the following Task related permissions:\n\n* Create – yes/no – can create Tasks;\n* Assignment – all/own – whom can assign Tasks to;\n* Read – all/own – what Tasks can view;\n* Stream – all/own – access to the Tasks's Stream;\n* Edit – all/assigned/own – what Tasks can edit;\n* Stage Edit – all/assigned/own – what Tasks can move on the board;\n* Delete – all/own/no – what Tasks can delete.\n\nIt also defines one Project related permission:\n\n* Project Stream – yes/no – can view the Project's stream (as of v1.4).\n\n!!! note\n\n    If a project member has access to the project's stream but does not have access to a task, they can still see that task in the stream. But they cannot open it to view details.\n\n## Members\n\nThe Members panel is available in the Project's detail view, in the button under the the Teams tab. Here, the project owner can add or remove members as well as change their roles.\n\nIt's possible to add or remove members for multiple projects at once from the Projects list view.\n\n## Tasks\n\nIn the Project Management tool, a Task is represented by the *Project Task* entity type.\n\nA Project can have multiple Tasks. Tasks can belong to different Groups. Tasks can be re-ordered within a Group. Tasks are also placed in specific Stages of the Board.\n\nTasks can have Sub-tasks.\n\n### Status\n\nAvailable Task statuses:\n\n* Not Started\n* Started\n* Completed\n* Canceled\n* Deferred\n\nThe Status field is read-only: it cannot be edited explicitly. The status is updated automatically after changing the Stage value (moving the Task on the Board) and when completing or canceling the Task.\n\n### Stage\n\nThe *Stage* field indicates in which Stage a Task is placed on the Board. It also defines the Status of the Task.\n\nThe available Stages in a Project are defined by the assigned Project Board.\n\nA project member with the *Member* role has access to update the Stage field.\n\n### Group\n\nThe *Group* field defines in what Group a Task is placed in.\n\nWhen creating a new Task, the *Active Group* of the Project is pre-selected.\n\n### Task dependencies\n\nA Task can be dependent on multiple Tasks.\n\nThere are the following dependency types:\n\n* Finish to Start – the predecessor must be finished before the successor can be started;\n* Finish to Finish – the predecessor must be finished before the successor can be finished;\n* Start to Start – the predecessor must be started before the successor can be started;\n* Start to Finish – the predecessor must be started before the successor can be finished.\n\nThe dependency type can be omitted: in this case, the dependency will be only declarative but not required. Meaning, it will be possible to finish a successor Task regardless of the predecessor's status.\n\nThe default dependency type can be set at: Administration > Entity Manager > Project Task > Fields > Dependency Type.\n\nThe label color indicates the predecessor's task status. Gray – Not Started, Blue – Started, Green – Completed.\n\nThe task dependency feature can be enabled or disabled in the Project settings (dropdown next to Edit > Settings).\n\n### Owner\n\nThe Task's Owner is a User who oversees the Task. A User who created a Task automatically becomes the Task's Owner.\n\n### Assignee\n\nThe Assignee of a Task is a User who is responsible for performing the Task. A Task can be unassigned.\n\nOnly members of the Project can be selected as assignees.\n\n### Collaborators\n\nThe Collaborators feature can be enabled per project in the Project settings (dropdown next to Edit > Settings). Users who are collaborators can view the Task and post in its Stream. This feature is useful when multiple users perform the same task.\n\n### Timeline\n\nA Task can have a Date Start and Date End. Both are non-mandatory fields.\n\n### Priority\n\nAvailable priority values:\n\n- Low\n- Normal\n- High\n- Urgent\n\nThe Priority field can be enabled or disabled in the Project settings  (dropdown next to Edit > Settings).\n\n### Points\n\nIs meant to represent the relative complexity of the Task, amount of work needed to complete the Task. The field can be enabled or disabled in the Project settings (dropdown next to Edit > Settings).\n\nNote that if the team won't use Points, the administrator can hide the field in the Entity Manager.\n\n### Hours\n\nMay represent how many hours is required to complete the Task. The field can be enabled or disabled in the Project settings.\n\n### Sub-tasks\n\nA Task can have sub-tasks. A task that has sub-tasks can be completed only when all sub-tasks are completed or canceled.\n\nSub-tasks can be owned by and assigned to different Users.\n\nSub-tasks can be re-ordered by dragging and dropping.\n\n### Stream\n\nA Task has a Stream. The Stream can be used for communication between the Project's members. It also shows Task's updates.\n\n## Milestones\n\nA milestone is a significant point in a project's timeline that marks the completion of a key phase.\n\n## Groups\n\nA Project has a unique set of Groups. A project Owner or Editor can manage Groups of the Project – add, remove, and edit.\n\nTo add a new Group to the Project, open the *Plan* view, click *Create Group* from the dropdown next to the *Edit* button. To reorder existing groups, click *Reorder Groups* from the same dropdown, then use dragging to reorder listed groups.\n\nTasks are ordered within their Group. It's possible to reorder Tasks and move Tasks from one Group to another.\n\nA specific color can be assigned to a Group.\n\nWhen a new Task is added to a Group, it is placed either at the top or the bottom depending on the parameter Group's parameter *New Task Placement*.\n\n### Group type\n\nA specific type is assigned to every group. The following types are available:\n\n- Triage\n- Backlog\n- Work\n- Phase\n- Sprint\n\nThe *Work* type is set by default.\n\nOnly *Work*, *Phase* and *Sprint* groups are displayed on the Gantt chart.\n\nThe Project Task dashlet allows you to limit tasks by specific group types. For example, one may want to list only tasks from the Work and Sprint groups, or display only Triage tasks in a separate dashlet.\n\nGroup types are also useful for automation. For example, a workflow rule can be triggered when a task is moved to a Sprint group. A single rule can be applied across all projects.\n\nAnother application of group types is Dynamic Logic. For example, the Assignee field can be automatically required if a task is linked to a group of the Work type.\n\nThe Project Task entity type has a foreign field *Group Type*, which holds the type value of the related Group. It can be used in conditions of the Dynamic Logic.\n\n### Calendar\n\n*Requires EspoCRM v9.2.*\n\nProject Tasks can be displayed on the Calendar in read-only mode. For this, an administrator should enable Project Tasks under: Administration > Settings > General > Calendar Entity List. \n \n## Plan view\n\nHere, you can see Tasks in Groups. You can add new Groups, remove Groups, and reorder Groups. Here, you can also create, edit, and remove Tasks.\n\nBy using drag-and-drop, it's possible to reorder Tasks within a Group or move Tasks from one Group to another.\n\nTo reorder Groups, click *Reorder Groups* from the dropdown menu, use drag-and-drop, and then apply changes.\n\n![Plan](../../_static/images/extensions/project-management/plan.png)\n\n## Board view\n\nOn the Board view, tasks are visualized as sticky notes. This tool is also known as a Kanban board.\n\nIt's possible to drag tasks from one column to another and reorder tasks within a column. Columns represent task's Stages.\n\nStages of the board are defined by the Project Board assigned to the Project.\n\nThe Board view displays tasks from only one Group at a time. You can switch between Groups to view tasks from different ones.\n\n![Board](../../_static/images/extensions/project-management/board.png)\n\n## Gantt view\n\nThe Gantt view visualizes the timeline of a project. It shows:\n\n* start and end dates of tasks and their durations;\n* milestones;\n* tasks dependencies.\n\n![Gantt](../../_static/images/extensions/project-management/gantt.png)\n\nYou can drag Tasks to change their timeline and resize to change their duration. By holding the CTRL/⌘ key, you can select multiple Tasks and drag them together.\n\nIf you select two Tasks, you can manage their dependency:\n\n* add a dependency;\n* remove an existing dependency;\n* change the type of an existing dependency.\n\nThe order in which you select two tasks determines the direction of the dependency. You can also click on a dependency path to select two tasks which this path connects.\n\nWhen creating a task or milestone while another task is selected, it will create a dependent task in the same group right after the selected task.\n\nIf the default [Working Time Calendar](../../user-guide/working-time-calendar.md) is set in the system, non-working days will be highlighted with a darker background.\n\nThe Gantt view can be disabled for a specific Project in its Settings.\n\n## Project cloning\n\nA Project can be cloned along with its Groups and Tasks. Optionally, it's possible to also include: \n\n* Members\n* Task Owners\n* Task Assignees\n* Attachments\n\nThe Date Start should be set in the source Project. When cloning, the user needs to set a new Date Start for the Project. Dates of cloned Tasks will be calculated based on the difference between the source and cloned Projects.\n\nTo be able to clone a Project, the user should have *create* access to the Project scope and *edit* access to the source Project. To clone a Project, open the detail view and click the *Clone* action from the dropdown next to the *Edit* button.\n\nIf you clone a Project and then decide to remove it, it won't be possible until you remove all related Tasks.\n\n## Dashlet\n\nUsers can add the Project Task dashlet to their dashboard. They can add multiple such dashlets, each with different options.\n\nDashlet options:\n\n- Next X Days – the number of future days from which to display tasks;\n- Include Owned – to list tasks where the current user is the owner;\n- Include Shared – to list tasks where the current user is in collaborators;\n- Exclude Assigned to Me – to exclude tasks assigned to the current user;\n- Limit by Group Type – to list only tasks from specific group types; for example, exclude Backlog tasks;\n\n## Shortcut keys\n\n* `Ctrl + Backspace` – complete selected Tasks from the Plan view;\n* `Ctrl + Quote` – self-assign selected Tasks from the Plan view; only unassigned tasks are affected;\n"
  },
  {
    "path": "docs/extensions/sales-pack/bill-credits.md",
    "content": "# Bill Credits\n\n*As of Sales Pack v4.0.*\n\nBill credits are reversal transactions for bills – the same as credit notes to invoices.\n\nAccess to Bill Credits is controlled by Roles.\n\nA bill credit can be created from a bill.\n\nA bill credit can be allocated to a bill or multiple bills. Inbound payments can be allocated to a bill credit.\n\nA bill credit should be used to cancel an issued bill if the issuance locking in enabled in the system. Bill credits can be used to reduce the payable outstanding amount.\n\n## Automatic numbering\n\nThe prefix of the next number, the next number itself and the quantity of digits in the number can be configured at Administration > Entity Manager > Bill Credit > Fields > numberA.\n\n## Locking\n\nA Bill Credit can be locked if it's resolved or canceled. When a record is locked, a specific fields become read-only. An administrator can configure the field list at: Administration > Entity Manager > Bill Credit > Edit.\n\nIf the settings parameter *Forbid order unlocking* is checked, once a record is locked, it can be unlocked only by an administrator.\n"
  },
  {
    "path": "docs/extensions/sales-pack/bills.md",
    "content": "# Bills\n\n*As of Sales Pack v4.0.*\n\nBills represent invoices from suppliers.\n\nAccess to Bills is controlled by Roles.\n\nA bill can be created from a [purchase order](purchase-orders.md). To create a bill from a purchase order, in the purchase order detail view, click on the plus button in the Bills panels.\n\nOutbound payments and [bill credits](bill-credits.md) can be allocated to a bill. To be able to set a bill as paid or cancel an issued bill, you need to zero the amount due by allocating payments or bill credits.\n\nBill credits can be created from a bill to fully or partially reverse it.\n\n## Automatic numbering\n\nThe prefix of the next number, the next number itself and the quantity of digits in the number can be configured at Administration > Entity Manager > Bill > Fields > numberA.\n\n## Locking\n\nA Bill can be locked if it's completed or canceled. When a record is locked, a specific fields become read-only. An administrator can configure the field list at: Administration > Entity Manager > Bill > Edit.\n\nIf the settings parameter *Forbid order unlocking* is checked, once a record is locked, it can be unlocked only by an administrator.\n\n\n"
  },
  {
    "path": "docs/extensions/sales-pack/credit-notes.md",
    "content": "# Credit Notes\n\n*As of Sales Pack v3.0.*\n\nCredit Notes document adjustments made to previously issued invoices, such as returns, post-sale discounts, or error corrections.\n\nCredit notes can be created from an invoice or separately.\n\nA credit note can be allocated to one or more invoices. This reduces the outstanding amount of the invoice.\n\nAn outbound payment can be allocated to one or more credit notes. This is typically used when refunding an already paid invoice.\n\nIn the article:\n\n* [Printing to PDF](#printing-to-pdf)\n* [Sending in email](#sending-in-email)\n* [Locking](#locking)\n* [E-Credit notes](#e-credit-notes)\n\n## Printing to PDF\n\nCredit notes can be printed to PDF. This action is available in the dropdown next to Edit button on the Invoice detail view. Then, you will be prompted to select a template. More info about printing to PDF is available [here](../../user-guide/printing-to-pdf.md).\n\n### Templates\n\nSee the documentation [for quote templates](../../user-guide/quotes.md#templates).\n\n## Sending in email\n\nA Credit Note PDF can be sent in an email as an attachment. Open a credit note record, click the dropdown next to Edit button and then click Email PDF.\n\nThe default email template can be set by the administrator: Administration > Sales Pack Settings > Email Templates.\n\nTo have the Credit Note entity selected as the email's parent, the administrator should add the Credit Note entity type to the parent type list. Administration > Entity Manager > Email > Fields > Parent > Entity List. As of v3.0.\n\n## Locking\n\nAn Credit Note can be locked if it's completed or canceled. When a record is locked, a specific fields become read-only. An administrator can configure the field list at: Administration > Entity Manager > Credit Note > Edit.\n\nIf the settings parameter *Forbid order unlocking* is checked, once a record is locked, it can be unlocked only by an administrator.\n\n## E-Credit notes\n\nCredit notes can be exported to EN 16931 electronic credit notes in a UBL format.\n\nTo export a Credit Note to a UBL file, click **E-Credit Note** from the dropdown menu next to the **Edit** button on the Credit detail view. The UBL file can be also attached along with a PDF when sending a credit note in email.\n"
  },
  {
    "path": "docs/extensions/sales-pack/delivery-orders.md",
    "content": "# Delivery Orders\n\n*As of Sales Pack v2.0.*\n\nDelivery Orders document the shipment of products to customers.\n\nIf the Warehouses feature is enabled, every Delivery Order record must be associated with a Warehouse.\n\nMultiple Delivery Orders can be created from a single [Sales Order](../../user-guide/sales-orders.md). It may be reasonable when a delivery is split into parts or shipped from different warehouses.\n\nWhen a delivery order is issued, the stock quantities of the included products are reduced.\n\nThe Delivery Order statuses:\n\n* Draft – inventory is soft-reserved;\n* Ready – inventory is reserved;\n* In Progress – inventory is removed from stock;\n* Completed – inventory is removed from stock;\n* Canceled – inventory is unreserved or added back to stock (depending on the previous status);\n* Failed – inventory is removed from stock.\n\nAccess to Delivery Orders is controlled by Roles.\n\nIt's possible to print a Delivery Order to PDF and send the PDF in an email.\n\n## Locking\n\nA Delivery Order can be locked if it's completed or canceled. When a record is locked, a specific fields become read-only. An administrator can configure the field list at: Administration > Entity Manager > Delivery Order > Edit.\n\nIf the settings parameter *Forbid order unlocking* is checked, once a record is locked, it can be unlocked only by an administrator.\n\n## Sending delivery order in email\n\nA Delivery Order PDF can be sent in an email as an attachment. Open an Delivery Order record, click the dropdown next to Edit button and then click Email PDF.\n\nThe default email template can be set by the administrator: Administration > Sales Pack Settings > Email Templates.\n\nTo have the Delivery Order entity selected as the email's parent, the administrator should add the Delivery Order entity type to the parent type list. Administration > Entity Manager > Email > Fields > Parent > Entity List. As of v3.0.\n"
  },
  {
    "path": "docs/extensions/sales-pack/inventory-management.md",
    "content": "# Inventory Management\n\n*As of Sales Pack v2.0.*\n\nThe Inventory Management feature is available in [Sales Pack](https://www.espocrm.com/extensions/sales-pack/).\n\nThe Inventory Management feature allows tracking of product quantities, locations in warehouses, and transfers between warehouses. It allows validating product availability before selling it to a customer.\n\nThe Inventory Management feature is disabled by default. To enable it, you need to enable **Inventory Transactions** at Administration > Sales Pack (Settings).\n\nIn this article:\n\n* [Inventory Transactions](#inventory-transactions)\n* [Quantity](#quantity)\n* [Inventory Numbers](#inventory-numbers)\n* [Warehouses](#warehouses)\n* [Inventory Adjustments](#inventory-adjustments)\n* [Transfer Orders](#transfer-orders)\n* [Transaction compressing](#transaction-compressing)\n* [Formula functions](#formula-functions)\n\n## Inventory Transactions\n\nThe transactional model is used for the inventory management. Each transaction record represents an action performed on a specific inventory item. It includes the following fields:\n\n* Number – auto-increment number;\n* Product;\n* Quantity – a positive or negative value: positive for a movement in, negative for movement out;\n* Parent – a record that is generated the transaction; e.g. Receipt Order, Delivery Order;\n* Type – transfer, reserve, or soft-reserve;\n* Warehouse – what warehouse the transaction is related to;\n* Inventory Number – used for products tracked by number.\n\nAccess to Inventory Transactions is controlled by Roles. The administrator can allow specific users to read and/or create transactions.\n\nNote that usually users are not supposed to create transactions manually. Transactions are created automatically when the status of an order record is changed.\n\nThe following entity types automatically create inventory transaction records:\n\n* Delivery Order – items are removed from stock or reserved;\n* Receipt Order – items are added to stock;\n* Transfer Order – items are moved between warehouses or reserved before the move;\n* Inventory Adjustment – items added or removed;\n* Sales Order – items are soft-reserved before delivery is created.\n\n## Quantity\n\nThe following quantity values are available for a Product:\n\n* Available – all items excluding reserved and soft-reserved;\n* On Hand – all excluding reserved;\n* Soft-Reserved – selected for a Sales Order, or selected for a draft Delivery or Transfer;\n* Reserved – selected for a Delivery or Transfer;\n* In Transit – currently moved between warehouses;\n* On Order – ordered from a supplier and not yet received.\n\n!!! note\n\n    In some cases, the total available quantity displayed for a product may be less than the sum of available quantities across individual warehouses. This occurs because Sales Orders soft-reserve inventory. Since the Sales Order entity is not linked to a specific warehouse, the reservation is applied globally and does not directly reduce the quantities shown for each warehouse.\n\n    You can disable soft-reservation for Sales Orders by removing the *Ready* status from the Soft-Reserve status list. The parameter is available under: Administration > Entity Manager > Sales Order > Edit.\n\n## Inventory Numbers\n\nIt's possible to track specific products by Inventory Numbers. There are two type of numbers: Batch and Serial. The type of the Inventory Number is defined by the field *Inventory Number Type* in a Product.\n\nAccess to Inventory Numbers is controlled by Roles.\n\nFrom the Inventory Number detail view it's possible to view the **History**: receipts, deliveries, transfers between warehouses, and adjustments.\n\nIt's possible to view quantity for a specific Inventory Number.\n\n### Batch\n\nMultiple inventory items can be assigned to one Batch number.\n\nWhen inventory is received, Batch numbers should be assigned to products that are tracked by batch. It's possible to split a Receipt Order Item into multiple batches.\n\nWhen inventory is delivered to a customer, Batch numbers should be selected for products that are tracked by batch.\n\n### Serial\n\nOnly one inventory item can be assigned to one Serial number.\n\nWhen inventory is received, Serial numbers should be assigned to every item for products that are tracked by serial. It's possible to **Import Serial Numbers** from a CSV file within a Receipt Order.\n\nWhen inventory is delivered to a customer, Serial numbers should be selected for products that are tracked by serial.\n\n!!! important\n\n    You can create Batch or Serial numbers for a product only if that product is marked as tracked by Batch or Serial correspondingly.\n\n### Removal Strategy\n\nThe Removal Strategy is defined in a Product record. It determines how Inventory Numbers will be sorted when a user picks a number for a delivery or transfer order.\n\nAvailable options:\n\n* FIFO – first in, first out; sorted by *Incoming Date* in ascending order;\n* FEFO – first expired, first out; sorted by *Expiration Date* in ascending order;\n* LIFO – last in, first out; sorted by *Incoming Date* in descending order.\n\n## Warehouses\n\nThe Warehouses feature is disabled by default. It can be enabled at Administration > Sales Pack (Settings).\n\nAccess to Warehouses is controlled by Roles.\n\nThe Receipt Order and Delivery Order have the mandatory *Warehouse* field. When products are delivered to a customer, they can be shipped from multiple warehouses. In this case, you need to create multiple Delivery Orders.\n\nInventory can be moved between Warehouses with Transfer Orders.\n\nInventory from a specific Warehouse can be excluded from stock availability by disabling the *Available for Stock* field in the Warehouse record.\n\n\n## Transfer Orders\n\nTransfer Orders can be utilized only if the Warehouses feature is enabled. Access to Transfer Orders is controlled by Roles.\n\nTransfer Orders allow moving inventory between Warehouses. When a Transfer Order record has the *In Progress* status, its items are counted as In Transit. They do not belong to any warehouse while in this state.\n\n## Inventory Adjustments\n\nInventory Adjustments are used to correct inventory quantity manually. Within a single adjustment, it's possible to specify a new quantity for multiple products. You can also utilize Inventory Adjustments to enter initial stock quantities.\n\nIf the Warehouses feature is enabled, a specific warehouse must be selected for an adjustment.\n\nWhen an adjustment is *Started*, all the affected inventory will be locked in the entire system until the adjustment is *Complete*. It's not possible to reserve or transfer inventory that is being locked by a started adjustment.\n\nAccess to Inventory Adjustments is controlled by Roles.\n\n## Transaction compressing\n\nAs the Inventory Transaction table grows, the system may became slower to calculate product quantities. For this reason, there is the functionality that compresses the inventory transaction table.\n\nBalanced transaction pairs can be removed. E.g. when the same item quantity is reserved and then unreserved, it will generate two transactions with opposite quantity values.\n\nIf there are multiple transactions that differentiate only by quantity, they can be merged into one. The new quantity will be the sum of all.\n\nCompressing can be configured to be run automatically. You need to create **Inventory Transaction Compress** job at Administration > Scheduled Jobs.\n\nIt's also possible to run compressing manually from the CLI:\n\n```\nbin/command inventory-compress\n```\n\nOnly for transactions prior a specific date:\n\n```\nbin/command inventory-compress --before=2024-01-01\n```\n\nReceipt Orders, Delivery Orders and Transfer Orders can be marked as *Locked*. It will disallow changing their status and items. After that, it is possible to detach transactions from records that were locked. These detached transactions can be consequently compressed.\n\nDetaching can be configured to be run automatically. You need to create **Inventory Transaction Detaching** job at Administration > Scheduled Jobs.\n\nOr run from the CLI:\n\n```\nbin/command inventory-detach\n```\n\nIt's also possible create a scheduled job that automatically locks old Receipt Orders, Delivery Orders and Transfer Orders.\n\n\n## Formula functions\n\n*As of Sales Pack v3.0.*\n\n### ext\\product\\quantity\n\n`ext\\product\\quantity(PRODUCT_ID, [WAREHOUSE_ID])`\n\n### ext\\product\\quantityOnHand\n\n`ext\\product\\quantityOnHand(PRODUCT_ID, [WAREHOUSE_ID])`\n\n### ext\\product\\quantityReserved\n\n`ext\\product\\quantityReserved(PRODUCT_ID, [WAREHOUSE_ID])`\n\n### ext\\product\\quantityInTransit\n\n`ext\\product\\quantityInTransit(PRODUCT_ID)`\n\n### ext\\inventoryNumber\\quantityOnHand\n\n`ext\\inventoryNumber\\quantityOnHand(INVENTORY_NUMBER_ID, [WAREHOUSE_ID])`\n\n### ext\\inventoryNumber\\quantityReserved\n\n`ext\\inventoryNumber\\quantityReserved(INVENTORY_NUMBER_ID, [WAREHOUSE_ID])`\n\n### ext\\inventoryNumber\\quantityInTransit\n\n`ext\\inventoryNumber\\quantityInTransit(INVENTORY_NUMBER_ID)`\n"
  },
  {
    "path": "docs/extensions/sales-pack/issuance-locking.md",
    "content": "# Issuance locking\n\n*As of Sales Pack v4.0.*\n\nThe issuance locking mode enforces stricter rules on transaction behavior. You may need to have it enabled for a compliance purpose, or if you want to Espo as a billing software. Without issuance locking enabled, balance reports cannot guarantee correct results.\n\n!!! note\n\n    Not to be confused with the record locking.\n\nThe issuance locking can be enabled at Administration > Sales Pack Settings.\n\nIssuance locking affects the following document transactions:\n\n- Invoice\n- Credit Note\n- Bill\n- Bill Credit\n\nAnd the following settlement transactions:\n\n- Payment\n- Write-off\n\nTransaction issuance implies changing status from Draft to any other status except Canceled. Upon issuance, the boolean field *Issued* becomes true.\n\nIssued document transactions affect the balance regardless of their status. Issued settlement transactions (payments and write-offs) affect the balance unless their status is canceled.\n\nWith the issuance locking mode enabled, an issued transaction:\n\n- Cannot be unissued or removed.\n- Has certain fields locked for editing.\n- Cannot be completed if not cleared.\n- Cannot be canceled if not cleared (except for Payment and Write-off).\n\nFor document transactions, clearance implies that the Amount Due is zeroed. For settlement transactions, clearance implies that the Unallocated Amount is zeroed.\n\nIf a transaction was issued by a mistake, it's not possible to just remove it. To cancel a document transaction, you need to negate it with an opposite transaction first.\n\nHow transactions can be negated for cancellation:\n\n- Invoice can be negated with Credit Notes.\n- Credit Note can be negated by allocating it to an Invoice (often, it should be a Debit Note).\n- Bill can be negated with a Bill Credit.\n- Bill Credit can be negated by allocating it to a Bill.\n- Payment and Write-off can be canceled if they don't have allocations. If there are allocations, you need to remove them first.\n\nAs issued transactions are not fully protected from editing, it's reasonable to use the regular locking once the transaction is completed. The system will automatically lock the record once it is completed.\n\n## Issuance fields\n\nThe following read-only fields are automatically written on issuance:\n\n- Is Issued – set to true when issued;\n- Issued At – date and time when the transaction was issued;\n- Issued By – the user that initiated the issuance.\n\nNote that Issued At and Issued By are not available on the Detail layout by default.\n\n## System-level parameter\n\nTo disallow admin users to disable the issuance locking, set `salesForceIssuanceLocking` to true in the config file. Doing so may be necessary for a compliance purpose (such as GoBD).\n\n"
  },
  {
    "path": "docs/extensions/sales-pack/multi-currency.md",
    "content": "# Multi-currency\n\n*As of Sales Pack v4.0.*\n\nMulti-currency is activated when you have more than one currency set in the *Currency List* settings parameter. Currencies are configured at: Administration > Currency. Here you can specify which currencies to have available in the system, as well as the base, and the default currency. Here, you can also set currency rates.\n\nThe base currency is the company's local currency. Tax, sales and purchase reports use the base currency.\n\nThe default currency is pre-selected by default when documents and transactions are created. It can be the same as the base currency.\n\n## Transaction currency\n\nInvoices, Credit Notes, Bills, Bill Credits, and Payments have the *Currency Rate* field.\nAmounts (including tax amounts) are stored in both the document currency and the local currency.\n\nAllocations, Tax Line Items, and Tax Total Items store amounts in both currencies as well.\n\nFor a document with different local and document currencies, you can view total amounts in the local currency by clicking *View in Local Currency* from the menu next to the Edit button.\n\nThe currency rate is set to the today's exchange rate. If you change the document date (Date Invoiced or Date Paid) to an earlier date, if the exchange rate for that day differs, the system will suggest to set that rate.\n\nWhen a Credit Note is created from an Invoice, it inherits its currency rate. The same applies for Bill Credits.\n\n## FX gain/loss\n\nIf the exchange rates used for an invoice and its payment differ, a foreign exchange gain or loss arises. You can view the FX gain/loss amount for a particular allocation: the Invoice detail view > Allocations panel > click View for an allocation.\n\nThe same applies for Bills and Bill Credits.\n"
  },
  {
    "path": "docs/extensions/sales-pack/overview.md",
    "content": "# Sales Pack Overview\n\nSales Pack is an [extension](https://www.espocrm.com/extensions/sales-pack/) for EspoCRM.\n\nFeatures:\n\n* [Products](../../user-guide/products.md)\n* [Prices](prices.md)\n* Sales\n  * [Quotes](../../user-guide/quotes.md)\n  * [Sales orders](../../user-guide/sales-orders.md)\n  * [Invoices](../../user-guide/invoices.md)\n  * [Credit notes](credit-notes.md)\n  * [Delivery orders](delivery-orders.md)\n  * [Return orders](return-orders.md)\n  * [Write-offs](write-offs.md)\n  * [Subscriptions](subscriptions.md)\n* Purchases\n  * [Purchase orders](purchase-orders.md)\n  * [Receipt orders](receipt-orders.md)\n  * [Suppliers](suppliers.md)\n  * [Bills](bills.md)\n  * [Bill credits](bill-credits.md)\n* [Inventory management](inventory-management.md)\n* [Payments](payments.md)\n* [Taxes](taxes.md)\n* [Tax codes](tax-codes.md)\n* [Issuance locking](issuance-locking.md)\n* [Multi-currency](multi-currency.md)\n* [Reports](reports.md)\n"
  },
  {
    "path": "docs/extensions/sales-pack/payments.md",
    "content": "# Payments\n\n*As of Sales Pack v3.0.*\n\n*Compatible with EspoCRM v9.1 or greater.*\n\nIn this article:\n\n* [Payment entries](#payment-entries)\n* [Payment methods](#payment-methods)\n* [Payment channels](#payment-channels)\n* [Payment requests](#payment-requests)\n\n## Payment entries\n\nA Payment entry captures a single payment transaction, either inbound or outbound.\n\nAccess to Payments is controlled by Roles. Payments can be created from the Payments list view. Payments can also be created from the Invoice and Credit Note detail views.\n\nAn inbound payment can be allocated to one or more Invoices or Supplier Credits, an outbound payment can be allocated to one or more Credit Notes or Supplier Bills.\n\nWhen a payment amount is received, the payment entry is supposed to be set to the *Paid* status. After the payment amount is fully allocated, it has to be set to *Completed*.\n\nWhen the payment amount is received, the status of the payment entry should be set to *Paid*. Once the full amount has been allocated, the status has to be updated to *Completed*.\n\nIf a payment exceeds the invoices' outstanding amount, the surplus can be allocated later to future invoices of the customer.\n\nThe Party Type field has two options: Customer and Supplier. A payment with the Customer party type can be allocated to invoices or credit notes, depending on its direction. A payment with the Supplier party type can be allocated to bills or bill credits.\n\nA payment must be in the same currency as the document it's allocated to.\n\n## Payment methods\n\nA Payment Method must be specified for each Payment entry. By default, there's no any payment method in the system, hence\nan administrator needs to create at least one payment method.\nPayment method examples: Wire Transfer, Cash, Stripe.\n\nOnly an administrator can manage Payment Methods. Regular users can read payment methods if their Role grants access.\n\nA payment method can be marked as eligible for inbound, outbound, or both payment directions.\n\nYou can add text instructions for a specific inbound payment method. These instructions will appear on the payment link page.\n\nMultiple payment methods can be associated with a single Invoice, with one designated as primary.\n\nMultiple payment methods can be associated with an Account, with one designated as primary. When an Invoice is created for an Account, the account's payment methods are carried over to the invoice.\n\n## Payment channels\n\nAn inbound payment method can be associated with a specific Payment Channel, which encapsulates the credentials and settings for a particular payment provider.\n\nOnly an administrator can manage payment channels. Regular users cannot view payment channel records.\n\nOut of the box, the following providers are available:\n\n* Wire Transfer\n* SEPA Credit Transfer\n* SEPA Direct Debit\n\nProviders shipped separately:\n\n* [Stripe](../stripe-integration/index.md)\n\n### Wire Transfer\n\nA generic bank credit transfer. The payment channel record stores bank credentials, which can be presented to a customer on a payment link page.\n\nThe credentials are included in an E-invoice if the payment method is set for the invoice.\n\n### SEPA Credit Transfer\n\nThe payment channel record stores bank credentials, which can be presented to a customer on a payment link page.\n\nThe credentials are included in an E-invoice if the payment method is set for the invoice.\n\n### SEPA Direct Debit\n\nThe payment channel record stores bank credentials and the creditor identifier.\n\nA Direct Debit Mandate can be created for an Account.\n\nTo generate a payment XML file, you need to create a Payment Request with the method set to *SEPA Direct Debit*. Then, the button will be available on the Payment Request detail view.\n\nWhen *SEPA Direct Debit* is selected as the Invoice's payment method, the generated E-invoice file includes the bank credentials and mandate data.\n\n## Payment requests\n\nPayment Requests can be used to create unique payment links. Payment links can be sent to customers. No Espo user account is required to access these links.\n\nPayment instructions and bank credentials can be displayed on the payment link page. In the case of an automated payment channel like Stripe, the customer can make a payment from the payment link.\n\nPayment requests can be created from an invoice. The invoice's amount due will be automatically set as the amount of the payment request.\n\nAccess to payment requests is controlled by Roles.\n\n### Sending in email\n\nTo send a payment link in an email, click *Send in Email* from the dropdown next to the *Edit* button on the Payment Request detail view.\n\nAn administrator can select the default email template for payment requests: Administration > Sales Pack Settings > Email Templates > Payment Request Email Template.\n\nUse the placeholder `{PaymentRequest.paymentUrl}` in the email template for a link. Note that the link will automatically be appended to the email body if there's no URL placeholder in the email template.\n\nNote that you can also access the payment URL from a Formula script.\n\nIt is also possible to include payment links when sending an invoice in email. Use the following code in the email template:\n\n```\n<p>\n  {{#each paymentRequests}}\n    {{#if (equal status 'Pending') }}\n      <a href=\"{{paymentUrl}}\">Payment Link {{number}}</a><br>\n    {{/if}}\n  {{/each}}\n</p>\n```\n"
  },
  {
    "path": "docs/extensions/sales-pack/prices.md",
    "content": "# Prices\n\nProduct sales prices can be determined by:\n\n* price books (enabled by default);\n* product-level prices.\n\nBoth price sources can be enabled or disabled under Administration > Sales Pack (Settings). Both sources can be enabled\nsimultaneously. In this case, the product-level price is used as a fallback.\n\nIn this article:\n\n* [Price books](#price-books)\n* [Supplier prices](#supplier-prices)\n* [Tax inclusive pricing](#tax-inclusive-pricing)\n* [Import](#import)\n* [Mass update](#mass-update)\n\n## Price books\n\n*As of Sales Pack v2.0.*\n\nThe Price Books feature allows you to set different prices for the same product. A price book record contains prices for multiple products. One price book can contain different prices for a single product, applied for a specific effective date period or a specific item quantity.\n\nThe Price Books feature can be enabled or disabled under Administration > Sales Pack (Settings). Access to Price Books is controlled by Roles.\n\nThe Price Books list view can be accessed at Products > the top-right menu > Price Books.\n\nA price book can be associated with a specific Account. Note that the administrator needs to add the **Price Book** field to the *Detail* layout of the Account entity type to be able to associate accounts with price books.\n\nThe Quote, Sales Order and Invoice have the **Price Book** field. When a new record is created, the Price Book is carried over from the related Account. It's possible to change the Price Book for a specific document.\n\nA Price Book can have a **Parent Price Book** and so on. If there's no price found for a specific product in a Price Book, then the system will look up the price in the Parent Price Book.\n\nThe **Default Price Book** can be specified at Administration > Sales Pack (Settings). It will be used to fetch default prices when there's no Price Book associated with an order.\n\nWhen a product is added to a document as a line item and there's no price found in the related Price Book or there's no related Price Book, the Default Price Book will be used. If there's no Default Price Book, and product-level prices are enabled, the price from the Product record will be used. Otherwise, the price won't be set for the line item, and the user will need to set it manually.\n\nWhen a user changes the quantity in a line item, the system will look up the new unit price for the new quantity. If the new unit price is found, it will prompt the user to apply the new unit price. The user can reject and keep the previous price.\n\nIt is possible to apply a Price Book to already added line items. The **Apply Price Book** action is available from the dropdown menu next to the plus button that adds line items.\n\n### Min. Quantity\n\nIf set, the price applies only if the item quantity exceeds the specified value.\n\n### Effective dates\n\nThe Date Start and Date End fields determine when the price is applicable. The Date End is inclusive. Both the Date Start and the Date End fields are optional.\n\n### Rules\n\n*As of Sales Pack v2.2.*\n\nPrice Rules can be added to a specific Price Book. One Rule can modify the base price for multiple Products. It's possible to add or subtract a percentage of the price, apply rounding, add or subtract a specific amount.\n\n![Rule](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/extensions/sales-pack/price-rule.png)\n\n#### Target\n\nThe Target field determines when the Rule should be applied. The following options are available:\n\n* Product Category – applies to all Products of a specific Category, including sub-categories;\n* All – applies to all Products;\n* Conditional – when a specific condition is met.\n\nAn administrator can add custom Conditions at Administration > Price Rule Conditions. Created conditions then will be available on the Price Rule form. Conditions are defined with a [Formula](../../administration/formula.md) expression. An expression should return true or false.\n\nSpecial functions available for conditions:\n\n* `ext\\priceRule\\accountAttribute` – returns an Account attribute value, e.g. `ext\\priceRule\\accountAttribute('type')`;\n* `ext\\priceRule\\productAttribute` – returns a Product attribute value, e.g. `ext\\priceRule\\productAttribute('id')`.\n\nFormula based conditions make the pricing functionality highly flexible, allowing to implement a wide range of pricing models. See a few simple use cases below.\n\n**Use case 1:** A rule applied to Accounts with type Partner.\n\n```\next\\priceRule\\accountAttribute('type') == 'Partner'\n```\n\n**Use case 2:** A rule applied to Accounts that have already purchased the same product before.\n\n```\nrecord\\exists(\n    'SalesOrderItem',\n    'productId', ext\\priceRule\\productAttribute('id'),\n    'accountId', ext\\priceRule\\accountAttribute('id'),\n    'salesOrderStatus', 'Completed' \n)\n```\n\n#### Based On\n\nWhat to use as a base price.\n\n* Unit – the price for a quantity of 1 defined in the Price Book or the unit price defined in the Product record; Price Book rules are not taken into account;\n* Price Book – the price is obtained from the same Price Book with rules are applied;\n* Supplier – the price of the Supplier;\n* Cost – the cost specified in the Product record.\n\nUse the *Price Book* base if your Price Book defines prices based on a markup and you also want to give an additional discount upon those calculated prices.\n\n#### Percentage\n\nA percentage of the standard price to deduct or add.\n\n#### Rounding Method\n\n* Half Up\n* Up\n* Down\n\n#### Rounding Factor\n\nThe amount will be round off to the multiple of the specified value. E.g. if set to 100, prices will be 100, 400, 5200.\n\n#### Surcharge\n\nAn amount to add after percentage and rounding are applied. Use a negative number to subtract.\n\nTo make prices to end with *9.99*, specify *-0.01* surcharge and use pricing factor *10*.\n\n#### Min. Quantity\n\nIf specified, the rule applies only if the item quantity exceeds the value.\n\n#### Effective dates\n\nThe Date Start and Date End fields determine when the rule is applicable. The Date End is inclusive. Both the Date Start and the Date End fields are optional.\n\n## Tax inclusive pricing\n\n*As of Sales Pack v4.0.*\n\nTax inclusive pricing can be enabled for a price book. When a tax inclusive price book is selected for a document, all unit prices are treated as tax inclusive.\n\nIf the default price book is set as tax inclusive, documents without a selected price book will use tax inclusive pricing. In other words, if you want to use tax inclusive pricing by default, your default price book should be set to tax inclusive.\n\nTax inclusive pricing is available only for sales, it's not available for purchases.\n\n## Supplier prices\n\n*As of Sales Pack v2.0.*\n\nA *Supplier* record can have prices for specific products. These prices are used when adding products to a Purchase Order associated with that Supplier.\n\nA Supplier record can contain different prices for a single product: applied for a specific date period or a specific item quantity.\n\nIf there's no supplier price found for a product, and product-level prices are enabled (in settings), then the *Cost Price* of the product will be used as a unit price.\n\n## Import\n\nIt's possible to import Product Prices from a CSV file using the basic [Import tool](../../administration/import.md). To import into a specific Price Book, select that Price Book as a default field value at the second step of the Import.\n\nEach CSV row must be associated with a corresponding Product record. It can be:\n\n* The *Name* of the Product;\n* The *Part Number* of the Product (as of v8.2).\n\nIn the similar fashion, it's possible to import Supplier Prices.\n\n!!! tip\n\n    It's possible to export Product Prices from Espo, update prices in a spreadsheet software using formula and then, import new prices back into Espo.\n\n## Mass update\n\n*As of Sales Pack v2.3.*\n\nIt's possible to update prices for multiple records from the list view. Select specific records or all search results, then click **Actions** and **Update Price**. It will propose to enter a markup or discount, add a surcharge amount.\n\nMass price update is supported for:\n\n* Products (Cost, List and Unit price)\n* Product Prices\n* Supplier Product Prices\n\nThe Product Prices list view can be reached by: Products tab > top-right menu > Price Books > top-right menu > Product Prices.\n\nThe Supplier Product Prices list view can be reached by: Products tab > top-right menu > Suppliers > top-right menu > Supplier Product Prices.\n"
  },
  {
    "path": "docs/extensions/sales-pack/purchase-orders.md",
    "content": "# Purchase Orders\n\n*As of Sales Pack v2.0.*\n\nThe Purchase Orders feature is available in [Sales Pack](https://www.espocrm.com/extensions/sales-pack/).\n\nPurchase Orders are issued to suppliers. They specify the products the company needs to purchase from the supplier, along with their quantities and agreed prices.\n\nAccess to Purchase Orders is controlled by Roles.\n\nThe Purchase Order has the *Supplier* field. Upon selecting the supplier, the Purchase Order's address fields will be automatically populated. The selected supplier also determines prices that will be applied for products in the order.\n\nPurchase Orders can be printed to PDF and sent in an email.\n\nMultiple [Receipt Orders](receipt-orders.md) can be created from one Purchase Order. If Receipt Orders created for a Purchase Order do not fully cover all its items, the next created Receipt Order will include the missing items. You can also add extra items to the Receipt Order if needed.\n\nIn the article:\n\n* [Printing to PDF](#printing-to-pdf)\n* [Sending in email](#sending-in-email)\n* [Locking](#locking)\n\n## Printing to PDF\n\nPurchase Orders can be printed to PDF. This action is available in the dropdown next to the *Edit* button on the record detail view. Then, you will be prompted to select a template. More info about printing to PDF is available in the [article](../../user-guide/printing-to-pdf.md).\n\n### Templates\n\nSee the documentation [for quote templates](../../user-guide/quotes.md#templates).\n\n## Sending in email\n\nA Purchase Order PDF can be sent in an email as an attachment. Open a Purchase Order record, click the dropdown next to Edit button, and then click Email PDF.\n\nThe default email template can be set by the administrator: Administration > Sales Pack Settings > Email Templates.\n\nTo have the Purchase Order entity selected as the email's parent, the administrator should add the Purchase Order entity type to the parent type list. Administration > Entity Manager > Email > Fields > Parent > Entity List. As of v3.0.\n\n## Locking\n\nA Purchase Order can be locked if it's completed or canceled. When a record is locked, a specific fields become read-only. An administrator can configure the field list at: Administration > Entity Manager > Purchase Order > Edit.\n\nIf the settings parameter *Forbid order unlocking* is checked, once a record is locked, it can be unlocked only by the administrator.\n"
  },
  {
    "path": "docs/extensions/sales-pack/receipt-orders.md",
    "content": "# Receipt Orders\n\n*As of Sales Pack v2.0.*\n\nReceipt Orders are used to document products received from suppliers or returned by customers.\n\nIf the Warehouses feature is enabled, every Receipt Order record must be associated with a Warehouse.\n\nMultiple Receipt Orders can be created from a single [Purchase Order](purchase-orders.md), for example when deliveries are split into parts or sent to different warehouses. A Purchase Order must have status *Released* or *Complete* to be able to create a Receipt Order from it.\n\nReceipt Orders can be created from a [Return Order](return-orders.md).\n\nThe following Receipt Order statuses are available:\n\n* Draft;\n* Ready;\n* Completed – inventory is added to stock;\n* Canceled.\n\nIt's possible to lock a Receipt Order. Locking disables the ability to change the status and items.\n\nAccess to Receipt Orders is controlled by Roles.\n\nIt's possible to print a Receipt Order to PDF and send the PDF in an email.\n\nUpon receipt completion, stock quantities for the included products increase.\n\nWhen a Receipt Order contains products that are tracked by Batch or Serial numbers, to be able to complete the order, one needs to specify numbers for those products.\n\nIt's possible to import Serial numbers from a CSV file within a Receipt Order.\n\n## Locking\n\nA Receipt Order can be locked if it's completed or canceled. When a record is locked, a specific fields become read-only. An administrator can configure the field list at: Administration > Entity Manager > Receipt Order > Edit.\n\nIf the settings parameter *Forbid order unlocking* is checked, once a record is locked, it can be unlocked only by an administrator.\n"
  },
  {
    "path": "docs/extensions/sales-pack/reports.md",
    "content": "# Sales and Purchase Reports\n\n*As of Sales Pack v4.0.*\n\n!!! warning\n\n    The Sales Pack reports are integrated with the Reports feature of the Advanced Pack. You need the Advanced Pack extension installed to be able to use the reports.\n  \n\nTo create a report, follow: Reports tab > top-right menu > Create Internal Report. Select the needed report, after that you can to tweak the report's parameters and run preview. After the report is saved, it will be available in the system as a regular report record. You can assign the report to a specific team for access control purposes.\n\nAll reports use the base currency (which is the company's local currency). If you change the base currency in the system, the report will not show the result for previous transactions (which use the previous local currency).\n\nReports:\n\n- [Customer balances](#customer-balances)\n- [Customer aging](#customer-aging)\n- [Supplier balances](#supplier-balances)\n- [Sales tax summary](#sales-tax-summary)\n- [Purchase tax summary](#purchase-tax-summary)\n- [Sales list by tax code](#sales-list-by-tax-code)\n- [Sales revenue](#sales-revenue)\n- [Sales by customer](#sales-by-customer)\n- [Sales by product](#sales-by-product)\n- [Sales by category](#sales-by-category)\n- [Purchase expenditure](#purchase-expenditure)\n- [Purchases by product](#purchases-by-product)\n- [Ledger summary](#ledger-summary)\n\n!!! important\n\n    Reports that concern taxes require the tax codes feature to be enabled.\n\n## Customer balances\n\nDisplays opening balance, debits, credits, and closing balance for each customer. The Date and Accounts filters are available. By clicking a customer, you can view Invoices, Credit Notes, Payments, and Allocations that affect the balance for the selected date range.\n\nYou can configure the report to include customers with a zero balance or not.\n\n## Customer aging\n\nThe report shows outstanding customer balances grouped by how long they have been overdue. The following date brackets are used: Current, 1-30 days, 31-60 days, 61-90 days, and 91+ days.\n\nThe basis for the report be set to one of the following values:\n\n- Date Due\n- Installment Date Due\n- Date Invoiced\n\nYou click on a customer and on a date bracket to view the invoices that affect the balance for a particular row or column.\n\n## Supplier balances\n\nDisplays opening balance, debits, credits, and closing balance for each supplier. The Date and Accounts filters are available. By clicking a supplier, you can view Bills, Bill Credits, Payments, and Allocations that affect the balance for the selected date range.\n\nYou can configure the report to include supplier with a zero balance or not.\n\n## Sales tax summary\n\nDisplays a summary of taxes related to invoices and credit notes. The report can be used for VAT and sales tax report preparation.\n\nIn the report parameters, you need to select tax codes and the basis: Accrual or Cash. The report will show summary for each tax codes: the Base and the Tax amount.\n\n## Purchase tax summary\n\nDisplays a summary of taxes related to bills and bill credits. The report can be used for VAT and sales tax report preparation.\n\nIn the report parameters, you need to select tax codes and the basis: Accrual or Cash. The report will show summary for each tax codes: the Base and the Tax amount. \n\nIn the result table, clicking a tax code displays the tax items that contribute to the result.\n\n## Sales list by tax code\n\nThis report can be used for EU Sales List report preparation.\n\nThe report displays the following columns:\n\n- Account – a customer\n- Tax Code\n- Country – stored in the tax code record\n- Tax Number – VAT number, stored in the account record\n- Item Type – Goods or Service\n- Amount – total amount of sales\n\nIn the report parameters you need to select tax codes and an item type for each tax code (goods or service).\n\nIn the result table, clicking an account and tax code displays the invoices and credit notes that contribute to the result. \n\n## Sales revenue\n\nBreaks down revenue by date. The following date grouping options are available: Month, Quarter, Year, Week, Fiscal Quarter, Fiscal Year. The shipping amount can be optionally included in results.\n\nIn the result table, clicking a group displays the invoices and credit notes that contribute to the result. \n\n## Sales by customer\n\nBreaks down revenue by customer.\n\n## Sales by product\n\nBreaks down revenue by product. Product categories can be selected in the report parameters.\n\n## Sales by category\n\nBreaks down revenue by product category.\n\n## Purchase expenditure\n\nBreaks down purchases by date. The following date grouping options are available: Month, Quarter, Year, Week, Fiscal Quarter, Fiscal Year. The shipping amount can be optionally included in results.\n\nIn the result table, clicking a group displays the bills and bill credits that contribute to the result.\n\n## Purchases by product\n\nBreaks down purchase expenditure by product. Product categories can be selected in the report parameters.\n\n## Ledger summary\n\nThis report generates a consolidated journal entry for a selected date period. The result can be exported to CSV for further\nimport into an accounting software.\n\nFor example, a company may export the operational summary at the end of an accounting period and import it into its\nGeneral Ledger as a single journal entry. In this setup, Espo functions as an operational billing system \nand serves as the source of truth for billing transactions.\n\nFor each account category, a GL account number can be specified. This simplifies the import mapping process.\n\nPayment methods and tax codes can be split into separate lines, each can be assigned to a specific account number.\n"
  },
  {
    "path": "docs/extensions/sales-pack/return-orders.md",
    "content": "# Return Orders\n\n*As of Sales Pack v2.0.*\n\nReturn Orders are used to document product returned from customers. A Return Order can be created from a completed Sales Order. Multiple [Receipt Orders](receipt-orders.md) can be created from a single Return Order.\n\nIf the Warehouses feature is enabled, a Receipt Order record can be associated with a Warehouse the return is supposed to be shipped to.\n\nAccess to Return Orders is controlled by Roles.\n\n## Printing to PDF\n\nReturn Orders can be printed to PDF. This action is available in the dropdown next to Edit button on the Delivery Order detail view. Then, you will be prompted to select a template.\n\n## Sending in email\n\nA Return Order PDF can be sent in an email as an attachment. Open a Return Order record, click the dropdown next to Edit button and then click Email PDF.\n\nThe default email template can be set by the administrator: Administration > Sales Pack Settings > Email Templates.\n\nTo have the Return Order entity selected as the email's parent, the administrator should add the Return Order entity type to the parent type list. Administration > Entity Manager > Email > Fields > Parent > Entity List. As of v3.0.\n"
  },
  {
    "path": "docs/extensions/sales-pack/subscriptions.md",
    "content": "# Subscriptions\n\n*As of Sales Pack v4.0.*\n\nThe Subscription feature provides the ability to invoice customers on a recurring basis.\n\nIn this article:\n\n- [Subscription records](#subscription-records)\n- [Billing plans](#billing-plans)\n- [Periods](#periods)\n- [Subscription templates](#subscription-templates)\n- [Updates and proration](#updates-and-proration)\n\nAccess to Subscriptions is controlled by Roles.\n\nThe life cycle of subscriptions is controlled by the scheduled job *Control Subscriptions*. Make sure you have this job active at Administration > Scheduled Jobs.\n\nTerms:\n\n- Charge period. Defines the period used to calculate the subscription price For example, 1 Month or 1 Year.\n- Billing period. A period the customer is invoiced for. A billing period can include multiple charge periods. For example, a subscription with a 1-month charge period may be billed every 12 such periods, resulting in a single annual charge covering 12 months.\n- Grace period. A period during which the subscription remains active despite being unpaid.\n- Alignment period. An additional period used to align the subscription billing cycle to a specific day of the month. It is always shorter than one month and may be charged or free, depending on configuration.\n- Trial period. A free period at the start of the subscription.\n- Pause period. A period during which the subscription is suspended.\n\nSubscriptions use different product prices than one-time selling pricies. Subscription prices are also defined in price books, but they additionally specify the billing period, such as 1 month or 1 year.\n\n!!! note\n\n    A product can have both one-time selling prices and subscription prices.\n\n## Subscription records\n\nA Subscription entry represents one subscription.\n\n### Status\n\nA subscription can be in one of the following statuses:\n\n- Draft\n- Trial\n- Active\n- Paused\n- Stopped\n\nA subscription that is processed automatically can be in one of the following statuses: Trial, Active, and Paused. The system automatically transitions the subscription between these three statuses depending on the current period and billing conditions. The system changes the status to Stopped when the subscription reaches its End Date or remains unpaid after the grace period. When a subscription reaches the Stopped status, the system stops controlling its state – user intervention is required to reactivate it.\n\nA subscription status is automatically changed to Paused when it reaches a *Pause* period. A user can create such periods to temporarily suspend the subscription.\n\nA user can stop a subscription manually by setting the status to Stopped.\n\n### Billing state\n\nA subscription can be in one of the following billing states:\n\n- Clear. No action required.\n- Due. When there is a period with billing status *Invoiced*. The customer needs to pay.\n- Past Due. Same as Due, but the invoice is overdue.\n\nThe system updates billing states automatically depending on current conditions.\n\n### Billing plan\n\nThe subscription billing plan defines billing-related parameters for the subscription. See more about billing plans below.\n\n### Line items\n\nA subscription can have one or multiple line items. Each line item specifies a product, quantity and unit price. Only products marked as *Subscribable* can be added to a subscription. The product of the first line item is designated as a primary product of the subscription.\n\nWhen the system generates an invoice for a billing period, it carries over the line items from the subscription. While the quantity is preserved, the unit price is adjusted based on the billing period.\n\n### Tax profile\n\nA subscription must be associated with a Tax Profile. This tax profile will be applied for invoices.\n\n### Payment method\n\nThe selected payment method will be applied for invoices. The payment method of the related Account is automatically pre-selected when a subscription is created.\n\n### Price book\n\nSubscriptions can be linked to a Price Book which enables customer-specific pricing. The price book of the related Account is automatically pre-selected.\n\nIf the Price Book is not specified, then the default price book is used.\n\n### Fields\n\nAdditional fields in the Subscription entity type (not avaialble in the Detail layout by default, can be added):\n\n- Buyer Reference – value is copied to created invoices.\n- Purchase Order Reference – value is copied to created invoices.\n\n## Billing plans\n\nA Billing Plan encapsulates parameters for subscriptions. Each subscription is associated with a single billing plan, while a billing plan can be used by multiple subscriptions.\n\nAccess to Subscription Billing Plans is controlled by Roles. Billing plans are available under: Subscriptions tab > top-right menu > Billing Plans.\n\n### Parameters\n\n#### Charge period\n\nAn interval that defines how the subscription is charged and identifies which price book prices apply to the subscription plan. For example, if the period is set to 1 Month, the subscription will use product prices defined specifically for the '1 Month' period.\n\nThe list of charge periods available for billing plans and product prices is defined system-wide. An administrator can configure it under: Administration > Subscription Intervals. Interval values are defined by a number and unit. The following units are available: Day, Week, Month, and Year.\n\n#### Billing cycle length\n\nNumber of charge periods within a billing cycle. For example, if the cycle length is set to 12 and the charge period is 1 month, the customer will receive one invoice per year.\n\n#### Grace period days\n\nHow many days an unpaid subscription remains active after the invoice is overdue.\n\n#### Invoice due period days\n\nDefines how the invoice date due is calculated. The specified number of days is added to the invoice date (the day the invoice is issued).\n\n#### Invoice lead time days\n\nHow many days in advance of the next billing cycle an invoice is created. If it is set to 0, the invoice will be issued on the first day of the next billing cycle.\n\n#### Alignment\n\nEnables billing cycle alignment. The following alignment options are available:\n\n- Immediate. A prorated period is created first to align the billing cycle. The following period is a normal billing period.\n- Delayed. A normal billing period is created first. The following period is prorated to align the billing cycle.\n\n#### Alignment days\n\nAvailable if the alignment is enabled and the charge period unit is a month or a year.\n\nDefines month days the subscription will be aligned to. For example, if it is set to 1, subscriptions billing cycles will be aligned to the first day of month. If it is set to 31, then – to the last day of month. Multiple alignment days can be selected, for example 1 and 15 to align subscriptions to the beginning and the middle of the month.\n\n#### Alignment weekdays\n\nAvailable if the alignment is enabled and the charge period unit is a week.\n\nDefines week days the subscription will be aligned to. Multiple days can be selected.\n\n#### Alignment proration policy\n\nAvailable if the alignment is enabled.\n\nControls whether alignment prorated periods are charged. Available options:\n\n- No Charge. The alignment period will be always free for the customer.\n- Charge. The alignment period will be proportionally charged if the length exceeds the specified threshold.\n\n#### Alignment charge min. days\n\nAvailable if the alignment is enabled and the proration policy is set to *Charge*.\n\nAlignment prorated periods shorter than the specified number of days won't be charged. If the value is not specified, then the alignment period will always be charged.\n\n#### Create payment requests\n\nIf enabled, payment requests will be automatically created upon invoice creation.\n\n#### Send payment request\n\nIf enabled, then created payment requests will be also sent to customers in email.\n\n#### Send invoices\n\nCreated invoices will be also automatically sent to customers.\n\n## Periods\n\nA Period entry represents a billing, trial, alignment, or pause period. A sequence of periods defines the subscription's life cycle. A period has Date Start and Date End. Periods cannot overlap. The end date is exclusive – the end date of the previous period becomes a start date of the next period.\n\nThe system automatically creates next periods, automatically controls the life cycle of periods, and creates invoices and payments for active periods. A user can create and edit periods manually when needed. A user can also initiate invoice and payment creation manually by clicking *Process Billing* for a particular period.\n\n!!! note\n\n    Payments can be automatically created only if the subscription or the related account has at least one payment method specified.\n\nPeriods of a subscription are available in the subscription's detail view in a bottom panel.\n\n### Fields\n\n#### Type\n\nThere are the following period types:\n\n- Regular. The subscription is active during this period.\n- Pause. The subscription is suspended during this period.\n- Trial. The subscription is in trial status during this period.\n\n#### Status\n\nPeriod statuses:\n\n- Scheduled. The period is not yet started. The system creates scheduled periods automatically beforehand.\n- Active. The current active period.\n- Ended. The period has ended.\n- Canceled. The system can cancel a period in certain error situations. Or a user may set this status to cancel a period manually.\n\n#### Billing status\n\nBilling statuses:\n\n- Pending. Used when a paid period is created but an invoice has not yet been created.\n- Invoiced. An invoice is created for the period.\n- Settled. The invoice is paid or the period is free of charge.\n- Canceled. Can be used for canceled periods.\n\n#### Invoice automatically\n\nIf checked, an invoice for the period will be created automatically according the billing plan parameters. The parameter is available only if the billing status is Pending.\n\n#### Activate only if paid\n\nIf unchecked, the subscription always switches to Active at the start of the period. If checked, switching to Active also requires the billing status to be Settled.\n\nWhen a subscription created from a template, this parameter is automatically checked for the first paid period. This means that the subscription won't be set to Active until the period's billing status is settled (usually meaning that the customer has paid). Following periods will have this parameter disabled.\n\n## Subscription templates\n\nSubscription templates simplify subscription creation by defining reusable configuration parameters.\n\nAccess to Subscription Templates is controlled by Roles. Subscription templates are available under: Subscriptions tab > top-right menu > Subscription Templates.\n\n### Parameters\n\n#### Billings plans\n\nThe field defines which billings plans will be available for selection. For example, you can offer to select either a 1 month or 1 year billing plan.\n\n#### Trial period\n\nIf enabled, created subscriptions will have a trial period at the start.\n\n#### Trial period days\n\nThe length of the trial period in days.\n\n#### Fixed term\n\nIf enabled, created subscriptions will have a fixed duration. The duration is determined by a unit (month, year, week, or day) and a number.\n\n#### Items\n\nA template must have at least one product added in a line item. Only products marked as *Subscribable* are allowed. \n\nEach line item specifies a quantity. If *Fixed Qty* is checked for a line item, the exact same quantity will be used in a created subscription.\n\nIf *Fixed Qty* is not checked, then the line item quantity defined in the template will be multiplied by the quantity set upon subscription creation. For example, if the line item quantity is set to 10 and upon subscription creation the user set a quantity of 3, the result quantity for the item line will be 30. Use case example: A 10 GB storage is given per each seat.\n\n### Template usage\n\nTo use a subscription template, go to Subscriptions > top-right menu > Create with Template. Then, select the needed template. After this, the following fields will be shown:\n\n- Billing Plan. Pre-filled if the template has only one plan.\n- Start Date. Pre-filled with the today's date.\n- Trial period. Pre-checked if the template has the trial period is checked for the template.\n- Quantity. Defines quantities of the subscription line items.\n- Currency. If multiple currencies are available in the system.\n\nAfter filling the form, the page will be redirected to the subscription creation form with pre-filled values. Here, you need to select an Account the subscription is created for. Then, you can save the subscription.\n\n## Updates and proration\n\nTo update the line items of an existing subscription, a user can either edit the subscription directly or use the built-in update mechanism. In the latter case, the system automatically creates an invoice, a credit note, or both to prorate the change. The proration will be processed only if there is a Regular period entry with status *Invoiced* or *Completed* and this period is not yet ended.\n\n!!! note\n\n    If a Regular period is completed without an invoice (for example, the company decided to provide the service for free for that period), the proration mechanism is still activated by default. In such cases, avoid issuing an invoice and credit note by setting the update status right away to Completed, or edit the subscription directly bypassing the update process. \n    \n    You may still want to prorate the amount in cases when the net amount of the proration is a positive value but avoid crediting the customer when the net amount is negative (to avoid crediting the customer for a service they did not pay for). For this, use the update process but do not issue the credit note if the pre-calculated net amount is negative.\n\nTo initiate an update process, in the subscription's detail view, click the plus icon in the Updates panel.\n\nThe *Date* field value is pre-set with the today's date. Pick another date if needed. This date is used for proration calculation. The portion of the billed period that falls after this date will be prorated.\n\nSpecify the *Billing Action*: Draft or Issue. This defines the status of the invoice and credit note which will be created. If you select Issue, then the following checkboxes will show up:\n\n- Create Payment Request. The system will create the payment request with the amount due.\n- Send Payment Request. The system will send the payment request to the customer.\n- Send Invoice. The system will send the issued invoice to the customer.\n\nModify the line items of the subscription.\n\nThe system previews the three amount values: To Invoice, To Credit, and Net Amount.\n\nOnce the update record is saved, the subscription line items are immediately changed according to the line items specified in the update. The line items of the created update cannot be edited. To modify the subscription items again, you need to create a new update.\n\n### Update billing status\n\nThe billing status of an update record affects the life cycle of the subscription. An overdue invoice will switch the subscription to the Due billing state and will stop the subscription after the grace period.\n\n"
  },
  {
    "path": "docs/extensions/sales-pack/suppliers.md",
    "content": "# Suppliers\n\n*As of Sales Pack v2.0.*\n\nSuppliers can be accessed at Products > the top right menu > Suppliers or Purchase Orders > the top right menu > Suppliers. It's also possible add the Suppliers navbar tab.\n\nAccess to Suppliers is controlled by Roles.\n\nIt's possible to specify Supplier Prices for specific products. There can be multiple prices for the same product: for specific date range or quantity.\n\nWhenever a product is added to a Purchase Order, the system will look up the price in the associated Supplier.\n"
  },
  {
    "path": "docs/extensions/sales-pack/tax-codes.md",
    "content": "# Tax Codes\n\n*As of Sales Pack v4.0.*\n\nThe Tax Codes functionality is the foundation of the tax engine. A tax code is a unique identifier (like *VAT20* or *EXMPT*) that serves two important roles:\n\n- defines tax calculation logic;\n- provides reporting capabilities.\n\nEvery document line item must have an associated tax code, even when tax is not applicable (for this, zero-rate tax codes are used).\n\nTax codes can be enabled or disabled at Administration > Sales Pack Settings > Tax Codes. Having tax codes enabled is recommended.\n\nAccess to tax codes is controlled by Roles. Regular users can be granted with edit access. Users that do not have explicit access to the Tax Code scope in their roles, still are able to select tax codes when they create a document.\n\nTo manage tax codes go to: Administration > Tax Codes. Here, you can create tax codes.\n\nFor a saved document, to view how taxes were applied, click *View Tax Details* from the menu next to the *Edit* button. In case of cash basis taxes, you can view applied taxes from a Payment entry.\n\n### Tax code parameters\n\n#### Status\n\nIndicates whether the tax code is available in the system. Instead of removing tax codes that has been used in transactions, set them Inactive.\n\n#### Selectable\n\nIndicates that the tax code can be selected for line items. Disable this parameter for tax codes that are not meant to be used separately from a composite tax code.\n\n#### Fore Sales\n\nWhether the tax code can be used for sales transactions, such as Quote, Sales Order, and Invoice.\n\n#### For Purchases\n\nWhether the tax code can be used for purchase transactions, such as Purchase Orders and Bills.\n\n#### Type\n\nAvailable options:\n\n- Percentage. Tax rate is defined by a percentage value.\n- Fixed. A fixed amount tax. For example, $10 tax per each item regardless of the unit price.\n- Composite. Tax code defines multiple nested tax codes. Use this type when multiple taxes must be applied for a product.\n\n#### Rate\n\nA tax rate in percents. Available only for Percentage type.\n\n#### Base\n\nSpecifies which value is used as the tax base.\n\n- Net Amount. The amount excluding taxes.\n- Cumulative Total. The net amount plus all previously applied taxes. Has an effect only when the tax code is used in a composite tax.\n\n#### Apply to Proportional Shipping\n\nIf enabled, this tax code will be included in proportional shipping tax calculations. You may need to disable this parameter for certain tax codes used in a composite tax.\n\nIf the proportional method is not used, this parameter has no effect. The parameter is available only for Percentage type.\n\n#### Included in Price\n\nWhether the tax amount is included in the unit price.\n\nYou may need to enable this parameter for taxes like excise. For taxes like VAT or GST, this parameter usually should be disabled.\n\n#### Rounding Level\n\nDefines how tax amounts are rounded.\n\n- Line. Amounts are rounded on each line.\n- Total. Precise line-level amounts are summed and then rounded.\n\nThe parameter is available only Percentage type.\n\n#### Items\n\nAvailable for Composite type.\n\nTax codes that will be applied when this tax code is used for a line item. An order of taxes matters.\n\n#### Label\n\nAn optional label to be shown to customers. This label may be used in a PDF invoice. You may leave the label empty for taxes which are not supposed to be shown to customers.\n\n#### Country\n\nCan be used for reporting.\n"
  },
  {
    "path": "docs/extensions/sales-pack/taxes.md",
    "content": "# Taxes\n\n*As of Sales Pack v3.0.*\n\nWith the Tax feature you can manage taxes, such as VAT, GST, sales tax, excise, and other taxes.\n\nIn this article:\n\n* [Tax profiles](#tax-profiles)\n* [Tax classes](#tax-classes)\n* [Tax rules](#tax-rules)\n\nSee also:\n\n* [Tax codes](tax-codes.md)\n\n## Tax profiles\n\n!!! note\n\n    Tax Profile was named *Tax* in earlier versions.\n\nA tax profile defines how taxes are applied to a document.\n\nYou can access tax profiles at: Products > top-right menu > Tax Profiles. Or use the global search for quick access.\n\nAccess to tax profiles is controlled by Roles.\n\nA tax profile can be applied to:\n\n* Quotes\n* Sales orders\n* Invoices\n* Credit notes\n* Return orders\n* Purchase orders\n* Bills\n* Bill credits\n\nLine items added to a document automatically receive the tax rate according to the Tax Profile assigned to the document. It's also possible to re-calculate tax rates for already added items.\n\nTax profiles can be automatically assigned to new documents using [Tax Rules](#tax-rules).\n\nA tax profile defines:\n\n* Tax code\n* Shipping tax mode\n* Shipping tax code\n* Item rules\n\nIf tax codes are not enabled, a tax profile specifies a rate value instead of the tax code.\n\n### Tax code\n\nThe Tax Code field defines the standard (default) tax. When a tax profile is selected for a document, all line items will use its default tax code unless a specific item rule applies to the item's product.\n\n### Shipping tax mode\n\nThe *Shipping Tax Mode* defines how tax is applied to the shipping cost. Available modes:\n\n* Proportional – Applies tax to shipping proportionally based on the taxes of the items in the document. This is the most common mode.\n* Fixed – A specific tax is applied.\n\nIf the shipping tax mode is not specified, no tax will be applied to the shipping cost.\n\nWhen items on an invoice have different tax rates, the E-invoice will include separate shipping charge entries with their respective VAT rates.\n\n### Shipping tax code\n\nDetermines the tax code to apply to the shipping cost. Available only if the shipping tax mode is set to Fixed.\n\n### Item rules\n\nA tax profile can include item rules. Each item rule defines an override tax rate for a specific Tax Class. Item rules are ordered. The first rule that matches is applied, and the subsequent rules are skipped.\n\n!!! example\n\n    A product has a tax class named 'Zero-rated'. A tax item rule maps this tax class to a tax code with a zero rate. Then, every time the product is added to a document line, that tax code will be automatically set.\n\n## Tax classes\n\nOnly an administrator can manage tax classes. Regular users can read tax classes if they have access enabled in Roles. Regular users are able to associate products with tax classes provided they have access to the Tax Class scope.\n\nAn administrator can access tax classes via: Administration > Tax Classes.\n\nA single product can belong to one or more tax classes. While one class per product is usually sufficient, multiple classes may be necessary when the product's tax treatment differs across jurisdictions.\n\n## Tax rules\n\n!!! note\n\n    Not to be confused with item rules of the tax profile.\n\nTax rules enable automatic association of a created document with the appropriate Tax Profile.\n\nFor sales and purchases separate rule sets are used.\n\nOnly an administrator can manage tax rules. An administrator can access tax rules at: Administration > Tax Rules. Purchase rules can be accessed at: Administration > Purchase Tax Rules.\n\nOne tax rule defines a Tax Profile and conditions. These conditions are evaluated against the Account record the order is related to.\n\nWhen an order is created for a specific Account, the Tax Profile is automatically selected according to the evaluated tax rules.\n\nTax rules are ordered. The first rule that matches is applied, and the subsequent rules are skipped.\n\nA rule with empty conditions is always applied. Such a rule can be placed at the end of the list to act as a default.\n\nRules can be set as inactive. This is useful, for example, when VAT is charged only after sales exceed a designated threshold. The rule can then be enabled accordingly.\n\nIn most cases, rule conditions would check:\n\n* Country – To select the appropriate tax profile for a specific country.\n* Tax Number – If the VAT number is provided, then select the zero-rate tax profile. Reverse charge scenario.\n\n!!! note\n\n    The *Tax Number* field is available in the Account entity type. By default, it's not added to the layout.\n\n### Example\n\nLet's assume our company is based in Germany and sells domestically, within the EU, and worldwide simultaneously.\n\n| Condition                                                                        | Tax rule to apply           |\n|----------------------------------------------------------------------------------|-----------------------------|\n| **Domestic** (same country)                                                      | Use seller's local VAT rate |\n| **Intra-EU B2B** (customer is VAT registered)                                    | Reverse charge (0% VAT)     |\n| **Intra-EU B2C** (not VAT registered) and total cross-border B2C sales < €10,000 | Use seller's local VAT      |\n| **Intra-EU B2C** and threshold exceeded                                          | Use customer's country VAT  |\n| **Outside EU** (export)                                                          | Exempt (0% VAT)             |\n\nWe would need to create the following tax profiles:\n\n* Zero – to cover Intra-EU B2B and Outside EU;\n* Reverse charge – to cover all Intra-EU B2B;\n* Germany – to cover Domestic and Intra-EU B2C before threshold exceeded;\n* Separate records for each EU country we are going to sell to (B2C).\n\nFor each tax profile, we will create and select a unique tax code. \n\nWe would need to create the following tax rules.\n\n1\\. Domestic.\n\nThis rule will map Accounts from Germany to the *Germany* tax profile. In the rule's conditions, add a condition that checks whether the *Country* is set to Germany.\n\n2\\. Intra-EU B2B.\n\nThis rule will map Accounts from EU countries with the VAT number to the *Reverse charge* tax profile. In the rule's conditions, add an OR condition with child conditions for each EU country. Also add a condition checking whether the Tax Number is not empty.\n\n!!! note\n\n    You can use a custom field to designate an Account as EU based and set the value with formula. It will make defining the rule conditions simpler.\n\n!!! note\n\n    It may be reasonable to create separate reverse charge tax profile for each country for reporting reasons.\n\n3\\. Intra-EU B2C below threshold.\n\nThis rule will map Accounts from EU countries without the VAT number to the *Germany* tax profile.\n\nThis rule is supposed to be deactivated once total cross-border B2C sales exceeds €10,000.\n\n4\\. Separate Intra-EU B2C rules for each EU country.\n\nEach rule will map to a corresponding tax profile of the EU country.\n\nIt's important that these rules are placed after the previous rule (the order or rules matters).\n\n5\\. Outside EU.\n\nThis rule will be the last one. It will map to the *Zero* tax profile. It may not define any condition, acting as a default rule.\n\nIt's important that this rule is placed at the end.\n"
  },
  {
    "path": "docs/extensions/sales-pack/write-offs.md",
    "content": "# Write-offs\n\n*As of Sales Pack v4.0.*\n\nWrite-offs allow settling an outstanding invoice balance without receiving or issuing a payment. They are commonly used for minor discrepancies, rounding differences, or immaterial amounts deemed uncollectible.\n\nWrite-offs are allocated to invoices the same way as payments or credit notes.\n\n!!! warning\n\n    As write-offs do not include line-items, they should not be used when a reduction in tax liability is required.\n    They also should not be used to cancel an entire invoice. In such cases, credit notes should be used instead.\n\nAccess to Write-offs is controlled by Roles.\n\nWrite-offs are available at: Invoices tab > top-right menu > Write-offs. Or you can use the global search for quick access. An administrator can add the Write-offs tab to the navbar.\n\nYou can create a write-off for an invoice from the invoice detail view, from the top-right menu. The outstanding amount will be pre-filled in the write-off's amount field.\n"
  },
  {
    "path": "docs/extensions/stripe-integration/index.md",
    "content": "# Stripe Integration\n\nThe integration allows your customers to make one-time payments using Stripe. Available in [extension](https://www.espocrm.com/extensions/stripe-integration/).\n\nThe Stripe integration requires:\n\n- [Sales Pack](https://www.espocrm.com/extensions/sales-pack/) extension\n- EspoCRM v9.1 or greater\n\nCheck this [article](../sales-pack/payments.md) to learn about the payments feature in Sales Pack.\n\n## Setting up\n\n!!! important\n\n    The integration relies on Stripe's webhooks. Your Espo instance must be accessible to Stripe.\n\n### Create webhooks in Stripe\n\nGo to Stripe Dashboard > Developers > Webhooks.\n\nClick *Add destination*.\n\nSelect all the following Checkout events:\n\n* checkout.session.async_payment_failed\n* checkout.session.async_payment_succeeded\n* checkout.session.completed\n* checkout.session.expired\n\nThen, choose the Webhook endpoint, as we are creating a webhook.\n\nSpecify the following endpoint URL: `https://your-host/api/v1/Stripe/webhook`. You can obtain the proper URL in Espo under Administration > Payment Channels > Create Payment Channel.\n\n### Create payment channel in Espo\n\nCreate a Payment Channel under Administration > Payment Channels, and select *Stripe* in the Provider field. Enter your Stripe keys and the webhook key, which you can obtain from the Stripe Dashboard.\n\nYou may name the payment channel *Stripe*.\n\n### Create payment method in Espo\n\nCreate a Payment Channel under Administration > Payment Methods, and select the previously created channel. You may name the method *Stripe*.\n\n## Trying out\n\n1. Create a Payment Request, select the created Stripe method, and enter the amount. Set the status to *Pending*.\n2. After the request is created, the payment URL will be generated. You can send this URL to your customer so that they can pay via Stripe.\n3. Once the customer paid, the status of the Payment Request will automatically change to *Paid*.\n4. A Payment entry related to the Payment Request will be created with the status *In Progress*, and will automatically change to *Paid* shortly after (by cron).\n\n## Testing in local environment\n\nAs webhooks require your Espo instance being accessible to Stripe, testing the integration in a local environment may need a few tweaks. To test the integration in a local environment, you can use Stripe CLI or a tunnel service (e.g., ngrok).\n\n### Using Stripe CLI\n\nStripe CLI provides the ability to forward Stripe events to your local webserver. You don't need to create webhooks in the Stripe Dashboard for this (though you will need to create them for production).\n\nDownload the [Stripe CLI](https://docs.stripe.com/stripe-cli) tool and run it in the terminal.\n\nRun the command:\n\n```\nstripe listen --forward-to localhost/api/v1/Stripe/webhook\n```\n\nWhere *localhost* should be replaced with the actual local address of your Espo instance.\n\nIt will print the webhook secret key. Specify this key in the payment channel record in Espo.\n\nKeep the process running while you are testing the integration.\n"
  },
  {
    "path": "docs/extensions/voip-integration/3cx-integration-setup.md",
    "content": "# 3CX Integration Setup\n\n3CX integration is available as part of [VoIP Integration extension](https://www.espocrm.com/extensions/voip-integration/). It allows you to integrate EspoCRM with 3CX server and other VoIP providers, read more details [here](https://www.espocrm.com/features/3cx-integration/).\n\n!!! note\n\n    Due to the way 3CX handles call events, the call pop-up in EspoCRM will only appear after the call has ended. This is a limitation of the 3CX PBX platform itself and not of EspoCRM. Once the call is complete, you’ll see the contact information and call details window in CRM as expected.\n\n!!! note\n\n    For the integration to work correctly, EspoCRM instance must be accessible by the 3CX server. The integration operates in Webhook mode, which requires EspoCRM to be reachable over the internet. If your CRM is hosted on a local or private network, or if external access is restricted, the integration will not function.\n\n## How to setup 3CX Integration for an administrator\n\nFill in the connection details of your 3CX server. To do this, go to the Administration (System panel) > Integrations > VoIP · 3cx.\n\n![3CX integration config](../../_static/images/extensions/voip-integration/3cx-admin-setup.png)\n\n* **Name** – name of your connection.\n* **3CX Web Client URL** – URL of your 3CX web client.\n* **Access Key to EspoCRM** – access key to EspoCRM for 3CX server.\n* **Default Country** – the country is used to format phone numbers.\n* **Dial Format for outgoing calls** – a phone number format for outgoing (click-to-call) calls.\n* **List of ignored numbers** – list of numbers which will be ignored. Popup window will not be displayed. Use numbers in the following formats: +14844608117 (full number match) or #4844608117# (regular expression).\n* **Permitted Entities** – entities that will be displayed in the popup window and will be used to identify a caller by his phone number.\n* **Apply global ACL for caller lookup** – apply global ACL rules (Administration > Roles) for caller lookup. This information is displayed in the popup window. If unchecked, no ACL restrictions are used.\n* **Hide call popup window** – automatically process call pop-ups without displaying them.\n* **Hide a Lead** – hide a Lead in a call popup when Account / Contact are available.\n* **Display Accounts related to Contacts** – display only Accounts related to Contacts.\n* **Listen recorded calls** – if you want to have possibility to listen recorded calls. This option should also be enabled in your telephony server.\n* **Upload recording?** – enables uploading recordings into EspoCRM.\n* **Automatically save a call** – automatically save incoming/outgoing calls in the system without having to press \"Save\" button.\n* **Automatically open the caller information** – automatically open the caller information for incoming/outgoing calls.\n* **Quick Create Entities** – entities which can be created through the call popup window.\n\n## How to setup 3CX Integration events\n\nTo handle incoming/outgoing calls, download the XML configuration from the side panel in the Administration (System panel) -> VoIP · 3cx, go to the 3CX Management Console -> “Settings” -> “CRM Integration”, click the “+ Add Template” button, and import the downloaded XML configuration.\n\n## How to setup 3CX Integration for users\n\nEach user who wants to use 3CX integration, should setup his access in the User’s Profile, under “VoIP Settings”. Also, the user can change some VoIP settings on this window.\n\n![VoIP settings](../../_static/images/extensions/voip-integration/3cx-user-settings.png)\n\n* **VoIP Server** – your current VoIP server.\n* **Your user extension** – your internal user extension (SIP user) of the 3CX server.\n* **Your VoIP password** – your password of the 3CX server.\n* **Display call notifications** – an option to enable/disable incoming/outgoing call notifications.\n* **Silent notifications** – mute notification sound.\n* **Use internal click-to-call** – an option to enable/disable the internal click-to-call feature. It is a feature to make outgoing calls through the 3CX server. If the checkbox is unchecked, then an external application will handle “tel:” links.\n* **User Dial Context** – Dial Context for a User. If it is empty, a Dial Context of a connector will be used.\n\n## Access control for users\n\nMake sure that your users have the access to the entity 'Calls'.\n\n* [Grant access to Calls](customization.md#grant-access-to-calls)\n\n## Summary and Transcript fields\n\nTo access Summary and Transcript fields, you need to drag these fields to the Call layout in EspoCRM. Go to Administration > Layout Manager > Calls and drag the corresponding fields to the layout you need.\n\n## Update 3CX Configuration File\n\nFollowing the upgrade of the VoIP Integration extension, it is necessary to update the XML Template on the 3CX Server side in order to ensure proper integration.\n\nThe steps to update are as follows:\n\n1\\. In the EspoCRM instance, go to the Administration > Integrations > VoIP · 3cx and download the latest version of the 3CX XML template.\n\n![VoIP settings 3cx update](../../_static/images/extensions/voip-integration/3cx-admin-update.png)\n\n2\\. Navigate to the 3CX Management Console > Settings > CRM Integration, and delete the existing template.\n\n![3cx integration CRM](../../_static/images/extensions/voip-integration/3cx-integrations-crm.png)\n\n3\\. Click on the `+ Add Template` button and upload the newly downloaded XML template.\n\n4\\. Save the changes.\n"
  },
  {
    "path": "docs/extensions/voip-integration/asterisk-integration-setup.md",
    "content": "# Asterisk Integration Setup\n\nAsterisk integration is available as part of [VoIP Integration extension](https://www.espocrm.com/extensions/voip-integration/). It allows you to integrate EspoCRM with Asterisk server through Asterisk Manager Interface (AMI) and other VoIP providers, read more details [here](https://www.espocrm.com/features/asterisk-integration-setup/).\n\n## Supported Asterisk servers\n\nVoIP Integration extension supports* the following Asterisk servers:\n\n* Asterisk 22\n* Asterisk 21\n* Asterisk 20\n* Asterisk 19\n* Asterisk 18\n* Asterisk 17\n* Asterisk 16\n* Asterisk 15\n* Asterisk 14\n* Asterisk 13\n\n\\* these servers were tested with VoIP Integration extension.\n\n## How to setup Asterisk Integration for an administrator\n\n#### Step 1:\nFill in the connection details of your Asterisk server. To do this, go to the Administration (System panel) > Integrations > VoIP · Asterisk AMI.\n\n![Asterisk integration config](../../_static/images/extensions/voip-integration/asterisk-admin-setup.png)\n\n* **Name** – name of your connection.\n* **Host** – IP or domain name of your Asterisk Server.\n* **Port** – a port for connection through AMI interface.\n* **Username** – AMI username.\n* **Password** – AMI user password.\n* **Protocol** – protocol for connection to Asterisk server (TCP, UDP, TLS).\n* **Dialout Channel** – channel format for outgoing calls. It can be “PJSIP/###” (Asterisk 13+) or “SIP/###”, where ### is a user’s extension (internal number). The extension “###” will be substituted automatically depending on the user.\n* **Dial Context** – context for dial actions.\n* **Connect Timeout** – timeout for connection to Asterisk server.\n* **Read Timeout** – timeout of read events from Asterisk server.\n* **Default Country** – the country is used to format phone numbers.\n* **Dial Format for outgoing calls** – a phone number format for outgoing (click-to-call) calls.\n* **List of ignored numbers** – list of numbers which will be ignored. Popup window will not be displayed. Use numbers in the following formats: +14844608117 (full number match) or #4844608117# (regular expression).\n* **Permitted Entities** – entities that will be displayed in popup window and will be used to identify a caller by his phone number.\n* **Apply global ACL for caller lookup** – apply global ACL rules (Administration > Roles) for caller lookup. This information is displayed in the popup window. If unchecked, no ACL restrictions are used.\n* **Hide a Lead** – Hide a Lead in a call popup when Account / Contact are available.\n* **Display Accounts related to Contacts** – display only Accounts related to Contacts.\n* **Automatically save a call** – Automatically save incoming/outgoing calls in the system without having to press \"Save\" button.\n* **Automatically open the caller information** – automatically open the caller information for incoming/outgoing calls.\n* **Access Key to EspoCRM** – an access key of EspoCRM to post data from Asterisk server.\n* **Listen recorded calls** – possibility to listen recorded calls in EspoCRM.\n* **Lines** – a prefix of phone numbers. E.g. UK phone number 702031112233 will be formatted like “7” – a line and “02031112233” – a phone number.\n* **Quick Create Entities** – entities which can be created through the call popup window.\n* **Active Queue Numbers** – a list of queue phone numbers which should be determined by EspoCRM.\n* **Display a popup only after answering the call** – do not show incoming call popups until the user answers a call.\n* **Experimental features** – test experimental features.\n\n#### Step 2:\n\nSetup a cron job (scheduled task) to handle Asterisk events (incoming/outgoing calls, hangup, etc.). It is very important to set it up to run every minute. The line that needs to be added is displayed in the right section of your Asterisk settings. For linux-based OS, it looks like:\n\n```\n* * * * * cd /var/www/html/espocrm; /usr/bin/php -f command.php voip Asterisk > /dev/null 2>&1\n```\n\nFor docker containers, see [here](#setting-up-cron-for-docker-container).\n\n\n## How to setup Asterisk Integration for users\n\nEach user who wants to use Asterisk integration, should setup his access in the User’s Profile, under “VoIP Settings”. Usually, it’s the SIP credentials. Also, the user can change some VoIP settings on this window.\n\n![VoIP settings](../../_static/images/extensions/voip-integration/asterisk-user-setup.png)\n\n* **VoIP Server** – your current VoIP server.\n* **Your user extension** – your internal user extension (SIP user) of the Asterisk server.\n* **Your VoIP password** – your password of the Asterisk server.\n* **Display call notifications** – an option to enable/disable incoming/outgoing call notifications.\n* **Silent notifications** – mute notification sound.\n* **Use internal click-to-call** – an option to enable/disable the internal click-to-call feature. It is a feature to make outgoing calls through Asterisk server. If the checkbox is unchecked, then an external application will handle “tel:” links.\n* **User Dial Context** – Dial Context for a User. If it is empty, a Dial Context of a connector will be used.\n\n## Access control for users\n\nMake sure that your users have the access to the entity 'Calls'.\n\n* [Grant access to Calls](customization.md#grant-access-to-calls)\n\n## Additional phone numbers for users\n\nEach user can add several additional phone numbers to handle incoming calls. They can be added in the User’s Profile.\nNote: Additional phone numbers are used for incoming calls only. Outgoing calls will use the internal user extension.\n\n![Phone numbers formats](../../_static/images/extensions/voip-integration/asterisk-additional-numbers.png)\n\n* **Phone numbers formats:** +442031112233, 00442031112233, 02031112233.\n\n## Setting up cron for Docker container\n\nTo display call pop-up windows and ensure the Asterisk provider works correctly in Docker, use either a daemon in the Docker Compose environment or add a cron job. For more information, see [Docker container setup](docker-container.md#asterisk).\n"
  },
  {
    "path": "docs/extensions/voip-integration/binotel-integration-setup.md",
    "content": "# Binotel Integration Setup\n\nBinotel integration is available as part of [VoIP Integration extension](https://www.espocrm.com/extensions/voip-integration/). It allows you to integrate EspoCRM with Binotel server and other VoIP providers, read more details [here](https://www.espocrm.com/features/binotel-integration/).\n\n\n## How to setup Binotel Integration for an administrator\n\n1\\. Fill in the connection details of your Binotel server. For this go to the Administration (System panel) > Integrations > VoIP · Binotel.\n\n![Binotel integration config](../../_static/images/extensions/voip-integration/binotel-admin-setup.png)\n\n* **Name** – name of your Binotel connector.\n* **Authorization Key** – authorization Key to the Binotel server.\n* **Authorization Secret** – authorization Secret to the Binotel server.\n* **Binotel API Version** – the version of the Binotel API which is used for integration.\n* **Access Key** – the key to access to EspoCRM to handle incoming/outgoing calls.\n* **Default Country** – The country is used to format phone numbers. E.g. 02011112222 for United Kingdom will be formatted to +442011112222.\n* **Dial Format for outgoing calls** – Phone number format for outgoing (click-to-call) calls.\nE.g. for \"+44 (203) 111-22-33\": {COUNTRY_CODE} - \"44\", {NATIONAL_NUMBER} - \"2031112233\".\n* **List of ignored numbers** – list of numbers, which will be ignored and popup window will not be displayed. Use numbers in the following formats: +14844608117 (full number match) or #4844608117# (regular expression).\n* **Permitted Entities** – entities that will be displayed in popup window and will be used to identify a caller by his phone number.\n* **Apply global ACL for caller lookup** – apply global ACL rules (Administration > Roles) for caller lookup. This information is displayed in the popup window. If unchecked, no ACL restrictions are used.\n* **Hide a Lead** – Hide a Lead in a call popup when Account / Contact are available.\n* **Display Accounts related to Contacts** – display an account related to the contact in the popup window.\n* **Automatically save a call** – automatically save incoming/outgoing calls in the system without having to press \"Save\" button.\n* **Automatically open the caller information** – automatically open the caller information for incoming/outgoing calls.\n* **Quick Create Entities** – entities which can be created through a call popup.\n* **Experimental features** – test experimental features.\n\n2\\. Contact Binotel support to add an URL (see “Post URL” field) to handle incoming/outgoing calls (API CALL Settings and API PUSH):\n**http://espocrm.local/?entryPoint=Binotel&connector=Binotel&key=hh9v0zr529**\n\n\n## How to setup Binotel Integration for users\n\nEach user who uses telephony should setup his user extension in User’s Profile, button “VoIP Settings”. Also, the user can disable a popup window for incoming/outgoing calls.\n\n![VoIP settings](../../_static/images/extensions/voip-integration/binotel-user-setup.png)\n\n* **VoIP Server** – VoIP server selection.\n* **Your user extension** – your Binotel user extension (e.g. “299”, “1001”).\n* **Your VoIP password** – your password to access to Binotel.\n* **Display call notifications** – if you want to receive incoming/outgoing call notifications.\n* **Silent notifications** – mute notification sound.\n* **Use internal click-to-call** – switching internal click-to-call possibility. Internal click-to-call is a feature to originate an outgoing call. If the checkbox is unchecked, then will be used an external application to handle tel: links.\n\n## Access control for users\n\nMake sure that your users have the access to the entity 'Calls'.\n\n* [Grant access to Calls](customization.md#grant-access-to-calls)\n"
  },
  {
    "path": "docs/extensions/voip-integration/customization.md",
    "content": "# VoIP Customization\n\nIn this article:\n\n* [Displaying a call recording](#displaying-a-call-recording)\n* [Grant access to Messages](#grant-access-to-messages)\n* [Grant access to Calls](#grant-access-to-calls)\n* [Add click-to-call feature to a custom entity](#add-click-to-call-feature-to-a-custom-entity)\n* [Add custom entities to Permitted Entities](#add-custom-entities-to-permitted-entities)\n* [Add custom entities to Quick Create Entities](#add-custom-entities-to-quick-create-entities)\n* [Event information in Permitted / Quick Create Entity](#event-information-in-permitted-quick-create-entity)\n* [Adding a call name to a call popup](#adding-a-call-name-to-a-call-popup)\n* [Format phone number](#format-phone-number)\n* [Call recording for Asterisk](#call-recording-for-asterisk)\n* [Adding a custom call recording handler](#custom-call-recording-handler)\n* [Adding a custom ApiClient](#custom-apiclient)\n* [Adding a custom EventListener](#custom-eventlistener)\n* [Adding a custom WebhookHandler](#custom-webhookhandler)\n* [Adding a custom CidManager](#custom-cidmanager)\n* [Adding a custom Call attribute](#custom-call-attribute)\n* [Additional info](#additional-info)\n\n\n##  Displaying a call recording\n\nFor displaying call recordings in EspoCRM, go to Administration > Layout Manager > select Calls entity and add the field \"Recording\" for Detail layout. See the screenshot:\n\n![Displaying call recording](../../_static/images/extensions/voip-integration/call-recording.png)\n\nAfter that, clear a local cache (Menu > Clear Local Cache).\n\n\n## Grant access to Messages\n\nBy default regular users don’t have access to Message entity. Administrator needs to grant access to this entity:\n\n1. Login as Administrator in EspoCRM.\n2. Navigate to the Administration > Roles.\n3. Create / edit a Twilio role.\n4. Grant access to the Message entity.\n\n![Twilio role](../../_static/images/extensions/voip-integration/twilio-role.png)\n\nBy default the Message entity tab should be added into the tab list.\n\n![Message tab](../../_static/images/extensions/voip-integration/message-tab.png)\n\n## Grant access to Calls\n\nDon't forget to give users access to the entity '**Calls**', so that they could make and accept calls. Go to the needed **User** > **Roles**.\n\nSelect the role or create a new one. Turn on '**Enabled**' access to the entity '**Calls**' and click '**Save**'.\n\n## Add click-to-call feature to a custom entity\n\nTo add a click-to-call feature to a custom entity you have to create/edit a file `/custom/Espo/Custom/Resources/metadata/entityDefs/<YOUR_ENTITY>.json`.\n\nIn this file should be defined a phoneNumber field (a field with \"type\": \"phone\"). Add the following line to this field:\n\n```\n{\n    \"fields\": {\n        \"phoneNumber\": {\n            ......,\n            \"view\": \"voip:views/fields/phone\"\n        }\n    }\n}\n```\n\nMake sure that your JSON data is correct after changes.\n\nTo take effect, clear a system cache (Administration > Clear Cache) and reload a page in your browser.\n\n\n## Add custom entities to Permitted Entities\n\n**Important**: the added entity must be of the `Person` type.\n\nTo add some custom entities to Permitted Entities, create/modify the file `/custom/Espo/Custom/Resources/metadata/integrations/<CONNECTOR_NAME>.json` with the code:\n\n(e.g. for Asterisk connector it's the file `/custom/Espo/Custom/Resources/metadata/integrations/Asterisk.json`)\n\n```\n{\n    \"fields\": {\n        \"permittedEntities\": {\n            \"options\": [\n                \"__APPEND__\",\n                \"<YOUR_CUSTOM_ENTITY>\"\n            ]\n        }\n    }\n}\n```\n\nMake sure that your JSON data is correct after changes.\nTo take effect, clear a system cache (Administration > Clear Cache) and reload a page in your browser.\n\n## Add custom entities to Quick Create Entities\n\nTo add some custom entities to Quick Create Entities, create/modify the file `/custom/Espo/Custom/Resources/metadata/integrations/<CONNECTOR_NAME>.json` with the code:\n\n(e.g. for Asterisk connector it's the file `/custom/Espo/Custom/Resources/metadata/integrations/Asterisk.json`)\n\n```\n{\n    \"fields\": {\n        \"quickCreateEntities\": {\n            \"options\": [\n                \"__APPEND__\",\n                \"<YOUR_CUSTOM_ENTITY>\"\n            ]\n        }\n    }\n}\n```\n\nMake sure that your JSON data is correct after changes.\nTo take effect, clear a system cache (Administration > Clear Cache) and reload a page in your browser.\n\n## Event information in Permitted / Quick Create Entity\n\nThere is a way to get event information while creating a `Permitted` / `Quick Create` entity.\n\nFor example, if we need to fetch a `phoneNumber` into the `description` field for a **Task** entity:\n\n1\\. Add the field in `custom/Espo/Custom/Resources/metadata/entityDefs/Task.json`:\n\n```\n{\n    \"fields\": {\n        \"voipEventData\": {\n            \"type\": \"jsonObject\",\n            \"notStorable\": true\n        }\n    }\n}\n```\n\n2\\. Make rebuild and grant the [necessary permissions](https://docs.espocrm.com/administration/server-configuration/#permissions).\n\n3\\. Add the following formula in `Administration` > `Entity Manager` > `Task` > `Formula` > `Before Save Custom Script`:\n\n```\n$voipEventData = json\\encode(voipEventData);\ndescription = json\\retrieve($voipEventData, 'phoneNumber');\n```\n\nIn addition to `phoneNumber`, additional data such as `id`, `status`, `type`, `assignedUserId`, etc., can be fetched from `voipEventData`. All data can be viewed after adding the `voipEventData` field to a layout.\n\n## Adding a call name to a call popup\n\nTo display a Call name field in a call popup, create/modify the file `custom/Espo/Custom/Resources/metadata/app/popupNotifications.json` with the code:\n\n```\n{\n    \"voipNotification\": {\n        \"additionalFields\": {\n            \"callName\" : {\n                \"display\": true,\n                \"fullWidth\": true,\n                \"entity\": \"Call\",\n                \"field\": \"name\",\n                \"order\": 9\n            }\n       }\n    }\n}\n```\n\n* default order is 10.\n\nMake sure that your JSON data is correct after changes.\nTo take effect, clear a system cache (Administration > Clear Cache) and reload a page in your browser.\n\n## Format phone number\n\nWhen a telephony server returns a phone number in a wrong format e.g. `004959123456789@SIP-PROVIDER-154303332258115083be1`. To get this number in a normal format, create/edit a file `custom/Espo/Custom/Resources/metadata/app/voip.json` and add the code:\n\n```\n{\n    \"phoneNumberReplacement\": {\n        \"Asterisk\": {\n            \"^goip-.*?\\\\/\": \"\",\n            \"@SIP-PROVIDER.*\": \"\"\n        }\n    }\n}\n```\n\nwhere\n\n* \"Asterisk\" - a connector ID;\n* \"@SIP-PROVIDER.\\*\" - regular expression to find unnecessary characters;\n* \"\" - a string for replacing.\n\nNote: JSON format has its own quoting, e.g. a symbol \"/\" should be quoted like \"\\\\/\".\n\nThen go to Administrator panel > Clear cache.\n\n\n## Call recording for Asterisk\n\nThe call recording should be configured on the Asterisk side, the URL of that recording will be saved in EspoCRM.\n\nThe setup process:\n\n1\\. Configure a call recording on the Asterisk side.\n\n2\\. Login to EspoCRM under the administrator and go to the Asterisk connector (Administration > VoIP Settings > Asterisk AMI).\n\n3\\. Enable the \"Listen recorded calls\" option and configure the \"URL to recorded calls\" field.\n\nPossible parameters:\n\n* \"{VOIP_UNIQUEID}\" - uniqueid of a call;\n* \"{Y}\" - year of a call;\n* \"{m}\" - month of a call;\n* \"{d}\" - day of a call.\n\nExample:\nIf we have a link in a format: \"http://11.11.11.11/2019/11/25/1568202771.6.mp3\", then the \"URL to recorded calls\" should be the following:\n`http://11.11.11.11/{Y}/{m}/{d}/{VOIP_UNIQUEID}.mp3`\n\n4\\. Display a call recording field in a layout of Call entity.\n\nFor displaying a call recording field in EspoCRM, go to Administration > Layout Manager > select Calls entity and add the field \"Recording\" for Detail layout. See the screenshot:\n\n![asterisk-call-recording](../../_static/images/extensions/voip-integration/call-recording.png)\n\nAfter that, clear a local cache (Administration > Clear Cache).\n\n## Custom call recording handler\n\nIf the standard functionality doesn't meet your recording processing needs, you can implement a custom call recording handler. For example, here's how you can customize it for the `Asterisk` connector:\n\n1\\. Create a file located at `custom/Espo/Custom/Modules/Voip/Providers/Asterisk/Recording.php` with the code:\n\n```php\n<?php\n\nnamespace Espo\\Custom\\Modules\\Voip\\Providers\\Asterisk;\n\nuse Espo\\Modules\\Voip\\Entities\\VoipEvent;\n\nclass Recording extends \\Espo\\Modules\\Voip\\Providers\\Asterisk\\Recording\n{\n    public function process(VoipEvent $voipEvent, string $triggeredBy): void\n    {\n        // YOUR CUSTOM CODE\n    }\n}\n```\n\n2\\. Create / edit a file `custom/Espo/Custom/Resources/metadata/app/voip.json`:\n\n```json\n{\n    \"recordingProcessorClassNameMap\": {\n        \"Asterisk\": \"Espo\\\\Custom\\\\Modules\\\\Voip\\\\Providers\\\\Asterisk\\\\Recording\"\n    }\n}\n```\n\n3\\. After saving, clear a local cache (Administration > Clear Cache).\n\n## Custom ApiClient\n\nFor adding a custom `ApiClient`, create a file located at `custom/Espo/Custom/Modules/Voip/Providers/YOUR_PROVIDER/ApiClient.php` with the code:\n\n```\n<?php\n\nnamespace Espo\\Custom\\Modules\\Voip\\Providers\\YOUR_PROVIDER;\n\nclass ApiClient extends \\Espo\\Modules\\Voip\\Providers\\YOUR_PROVIDER\\ApiClient\n{\n    // YOUR CUSTOM CODE\n}\n```\n\nAfter saving, clear a local cache (Administration > Clear Cache).\n\n## Custom EventListener\n\nFor adding a custom `EventListener`, create a file located at `custom/Espo/Custom/Modules/Voip/Providers/YOUR_PROVIDER/EventListener.php` with the code:\n\n```\n<?php\n\nnamespace Espo\\Custom\\Modules\\Voip\\Providers\\YOUR_PROVIDER;\n\nclass EventListener extends \\Espo\\Modules\\Voip\\Providers\\YOUR_PROVIDER\\EventListener\n{\n    // YOUR CUSTOM CODE\n}\n```\n\nAfter saving, clear a local cache (Administration > Clear Cache).\n\n## Custom WebhookHandler\n\nFor adding a custom `WebhookHandler`, create a file located at `custom/Espo/Custom/Modules/Voip/Providers/YOUR_PROVIDER/WebhookHandler.php` with the code:\n\n```\n<?php\n\nnamespace Espo\\Custom\\Modules\\Voip\\Providers\\YOUR_PROVIDER;\n\nclass WebhookHandler extends \\Espo\\Modules\\Voip\\Providers\\YOUR_PROVIDER\\WebhookHandler\n{\n    // YOUR CUSTOM CODE\n}\n```\n\nAfter saving, clear a local cache (Administration > Clear Cache).\n\n\n## Custom CidManager\n\nFor adding a custom `CidManager`, create a file located at `custom/Espo/Custom/Modules/Voip/Providers/YOUR_PROVIDER/CidManager.php` with the code:\n\n```\n<?php\n\nnamespace Espo\\Custom\\Modules\\Voip\\Providers\\YOUR_PROVIDER;\n\nclass CidManager extends \\Espo\\Modules\\Voip\\Providers\\YOUR_PROVIDER\\CidManager\n{\n    // YOUR CUSTOM CODE\n}\n```\n\nAfter saving, clear a local cache (Administration > Clear Cache).\n\n## Custom Call Attribute\n\nNote: This method is specifically designed to work with 3CX integration only.\n\nTo add a custom attribute for the Call entity, create or edit a file located at `custom/Espo/Custom/Resources/metadata/app/voip.json` with the code:\n\n```json\n{\n    \"callAttributes\": {\n        \"3cx\": [\n            \"__APPEND__\",\n            \"cAttribute\"\n        ]\n    }\n}\n```\n\nAfter saving, clear a local cache (Administration > Clear Cache).\n\n## Additional info\n\n**Dialout Channel** – channel format for outgoing calls.\n\nIt can be “SIP/###” or “PJSIP/###”, where ### is a user’s extension (internal number). The extension “###” will be substituted automatically depending on the user.\n"
  },
  {
    "path": "docs/extensions/voip-integration/docker-container.md",
    "content": "# VoIP configuration for Docker containers\n\n## Asterisk\n\nTo display call pop-up windows and ensure the Asterisk provider works correctly in the [Docker](../../administration/installation-by-script.md) instance, you need to use either a daemon in the Docker Compose environment or add a line to the [crontab](../../administration/server-configuration.md#setting-up-crontab). Choose one of these approaches (either the daemon or the crontab line).\n\n### Daemon (recommended)\n\n!!! note\n\n    This configuration is displayed for the [official EspoCRM container](../../administration/docker/installation.md#install-espocrm-with-docker-compose).\n\nAdd the following container to your `docker-compose.yml` file:\n\n```yml\nespocrm-daemon-voip:\n  image: espocrm/espocrm:latest\n  container_name: espocrm-daemon-voip\n  volumes:\n    - espocrm:/var/www/html\n  restart: always\n  entrypoint: []\n  command: [\"php\", \"/var/www/html/command.php\", \"voip\", \"Asterisk\"]\n```\n\n### Crontab line\n\n!!! important\n\n    This line should be added under `root` or other docker user.\n\n```bash\n* * * * * /usr/bin/docker exec --user WEBSERVER_USER -i ESPOCRM_DOCKER-CONTAINER /bin/bash -c \"cd /var/www/html; php -f command.php voip Asterisk\" > /dev/null 2>&1\n```\n\nReplace `WEBSERVER_USER` with one of the following values: `www-data`, `www`, `apache`, etc., depending on your web server.\n\n"
  },
  {
    "path": "docs/extensions/voip-integration/iexpbx-integration-setup.md",
    "content": "# iexPBX Integration Setup\n\niexPBX integration is available as part of [VoIP Integration extension](https://www.espocrm.com/extensions/voip-integration/). It allows you to integrate EspoCRM with iexPBX server and other VoIP providers, read more details [here](https://www.espocrm.com/features/iexpbx-integration/).\n\n## How to setup iexPBX Integration for an administrator\n\n#### Step 1:\n\nFill in the connection details of your iexPBX server. To do this, go to the Administration (System panel) > Integrations > VoIP · iexPBX.\n\n![iexPBX integration config](../../_static/images/extensions/voip-integration/iexpbx-admin-setup.png)\n\n* **Name** – name of your connection.\n* **Server URL** – URL of your iexPBX server.\n* **API User** – API user of your iexPBX server.\n* **API Secret** – API Secret of your iexPBX server.\n* **Access Key to EspoCRM** – the key to access to EspoCRM to handle incoming/outgoing calls.\n* **Default Country** – the country is used to format phone numbers.\n* **Dial Format for outgoing calls** – a phone number format for outgoing (click-to-call) calls.\n* **Call Recording** – if you want to have possibility to listen recorded calls. This option should also be enabled in your telephony server.\n* **List of ignored numbers** – list of numbers which will be ignored. Popup window will not be displayed. Use numbers in the following formats: +14844608117 (full number match) or #4844608117# (regular expression).\n* **Permitted Entities** – entities that will be displayed in the popup window and will be used to identify a caller by his phone number.\n* **Apply global ACL for caller lookup** – apply global ACL rules (Administration > Roles) for caller lookup. This information is displayed in the popup window. If unchecked, no ACL restrictions are used.\n* **Hide a Lead** – hide a Lead in a call popup when Account / Contact are available.\n* **Display Accounts related to Contacts** – display only Accounts related to Contacts.\n* **Automatically save a call** – automatically save incoming/outgoing calls in the system without having to press \"Save\" button.\n* **Automatically open the caller information** – automatically open the caller information for incoming/outgoing calls.\n* **Quick Create Entities** – entities which can be created through the call popup window.\n* **Experimental features** – test experimental features.\n\n#### Step 2:\n\nSetup webhooks on iexPBX server to handle incoming/outgoing calls. It can be done by login to a web panel of your iexPBX server, go to Settings > API Integrations and define two Webhooks:\n\n##### Call Event Webhook\n\n- Function: `Arama Bilgisi Gönder`\n- Fonksiyon 2: `Tümü`\n- Type: `GET olarak`\n- URL Address: `https://YOUR_ESPOCRM_URL/api/v1/Voip/webhook/IexPBX/YOUR_ACCESS_KEY?chanid={chanid}&src={src}&dst={dst}&type={calltype}`\n\n![iexPBX Webhook 1](../../_static/images/extensions/voip-integration/iexpbx-call-event-webhook.png)\n\n##### Call Status Webhook\n\n- Function: `Kapatma Bilgisi Gönder`\n- Fonksiyon 2: `Tümü`\n- Type: `GET olarak`\n- URL Address: `https://YOUR_ESPOCRM_URL/api/v1/Voip/webhook/IexPBX/YOUR_ACCESS_KEY?chanid={chanid}&status={status}&duration={duration}`\n\n![iexPBX Webhook 2](../../_static/images/extensions/voip-integration/iexpbx-call-status-webhook.png)\n\n\n## How to setup iexPBX Integration for users\n\nEach user who wants to use iexPBX integration, should setup his access in the User’s Profile, under “VoIP Settings”.\n\n![iexPBX User settings](../../_static/images/extensions/voip-integration/iexpbx-user-settings.png)\n\n* **VoIP Server** – select your iexPBX server.\n* **Your user extension** – your internal SIP extension for the iexPBX server (e.g. 101).\n* **Your VoIP password** – your SIP password for your iexPBX server.\n* **Display call notifications** – an option to enable/disable incoming/outgoing call notifications.\n* **Silent notifications** – mute notification sound.\n* **Use internal click-to-call** – an option to enable/disable the internal click-to-call feature. It is a feature to make outgoing calls through the iexPBX server. If the checkbox is unchecked, then an external application will handle “tel:” links.\n"
  },
  {
    "path": "docs/extensions/voip-integration/overview.md",
    "content": "# VoIP Integration extension\n\nThe VoIP Integration extension allows you to integrate EspoCRM with IP telephony servers/services.\n\n## Supported servers and services\n\n* [3CX PBX](3cx-integration-setup.md)\n* [Twilio service](twilio-integration-setup.md)\n* [Asterisk server](asterisk-integration-setup.md)\n* [Starface server](starface-integration-setup.md)\n* [Binotel service](binotel-integration-setup.md)\n* [iexPBX server](iexpbx-integration-setup.md)\n\n## Additional information\n\n* [Docker](docker-container.md)\n* [Customization](customization.md)\n* [Troubleshooting](troubleshooting.md)\n"
  },
  {
    "path": "docs/extensions/voip-integration/starface-integration-setup.md",
    "content": "# Starface Integration Setup\n\nStarface integration is available as part of [VoIP Integration extension](https://www.espocrm.com/extensions/voip-integration/). It allows you to integrate EspoCRM with Starface server and other VoIP providers, read more details [here](https://www.espocrm.com/features/starface-integration-setup/).\n\n## Supported Starface servers\n\nVoIP Integration extension supports* the following Starface servers:\n\n* Starface 9.0\n* Starface 8.1\n* Starface 8.0\n* Starface 7.3\n* Starface 7.2\n* Starface 7.1\n* Starface 7.0\n* Starface 6.7\n* Starface 6.6\n* Starface 6.5\n* Starface 6.4\n* Starface 6.3\n* Starface 6.2\n\n\\* These servers were tested with the VoIP Integration extension.\n\n## How to setup Starface Integration for an administrator\n\nFill in the connection details of your Starface server. To do this, go to the Administration (System panel) > Integrations > VoIP · STARFACE.\n\n![Starface integration config](../../_static/images/extensions/voip-integration/starface-admin-setup.png)\n\n* **Name** – name of your connection.\n* **Host of Starface server** – IP or domain name of your Starface Server.\n* **Port** – port for connection by AMI interface.\n* **Protocol** – protocol that is used for connection of Starface server (HTTP, HTTPS).\n* **Version of your Starface server** – version of your Starface server. This is an important option since Starface 6.4.2 is used a new authorization protocol.\n* **Access Key to EspoCRM** – the key to access to EspoCRM to handle incoming/outgoing calls.\n* **Default Country** – the country is used to format phone numbers.\n* **Dial Format for outgoing calls** – a phone number format for outgoing (click-to-call) calls.\n* **List of ignored numbers** – list of numbers which will be ignored. Popup window will not be displayed. Use numbers in the following formats: +14844608117 (full number match) or #4844608117# (regular expression).\n* **Permitted Entities** – entities that will be displayed in the popup window and will be used to identify a caller by his phone number.\n* **Apply global ACL for caller lookup** – apply global ACL rules (Administration > Roles) for caller lookup. This information is displayed in the popup window. If unchecked, no ACL restrictions are used.\n* **Hide a Lead** – Hide a Lead in a call popup when Account / Contact are available.\n* **Display Accounts related to Contacts** – display only Accounts related to Contacts.\n* **Automatically save a call** – Automatically save incoming/outgoing calls in the system without having to press \"Save\" button.\n* **Automatically open the caller information** – automatically open the caller information for incoming/outgoing calls.\n* **Quick Create Entities** – entities which can be created through the call popup window.\n* **Experimental features** – test experimental features.\n\n## How to setup Starface Integration for users\n\nEach user who wants to use Starface integration, should setup his access in the User’s Profile, under “VoIP Settings”. Note that login and password should be to the Starface web interface, not to the SIP credentials. Also, the user can change some VoIP settings on this window.\n\n![VoIP settings](../../_static/images/extensions/voip-integration/starface-user-settings.png)\n\n* **VoIP Server** – your current VoIP server.\n* **Your user extension** – your login ID for the Starface web interface.\n* **Your VoIP password** – your password for the Starface web interface.\n* **Display call notifications** – an option to enable/disable incoming/outgoing call notifications.\n* **Silent notifications** – mute notification sound.\n* **Use internal click-to-call** – an option to enable/disable the internal click-to-call feature. It is a feature to make outgoing calls through the Starface server. If the checkbox is unchecked, then an external application will handle “tel:” links.\n\n## Access control for users\n\nMake sure that your users have the access to the entity 'Calls'.\n\n* [Grant access to Calls](customization.md#grant-access-to-calls)\n\n"
  },
  {
    "path": "docs/extensions/voip-integration/troubleshooting.md",
    "content": "# VoIP Troubleshooting\n\nIn this article:\n\n* [How to report](#how-to-report)\n* [VoIP error debug](#voip-error-debug)\n* [Asterisk: The popup window is not displayed](#asterisk-the-popup-window-is-not-displayed)\n* [Asterisk: Click to call is not working](#asterisk-click-to-call-is-not-working)\n* [Starface: The popup window is not displayed](#starface-the-popup-window-is-not-displayed)\n* [Twilio: Unable to activate the phone number](#twilio-unable-to-activate-the-phone-number)\n\n## How to report\n\n1. Provide an EspoCRM log file with the [debug error information](#voip-error-debug).\n2. Provide an error description from the VoIP server side (if you have an access to a debugger or logger).\n3. Provide steps to reproduce the error.\n4. Provide screenshots with:\n  1. Administration > Integrations > VoIP integration configs;\n  2. Administration > VoIP Routing > Your VoIP number;\n  3. Defined phone numbers in the user profile (if a user can't make or receive a call).\n5. Describe details of this call:\n  1. Time of the call;\n  2. Caller phone number;\n  3. Called phone number.\n\n## VoIP error debug\n\n1. Enable debug mode as described [here](../../administration/troubleshooting.md/#debug-mode).\n2. Reproduce an error again.\n3. Get an EspoCRM [log file](../../administration/troubleshooting.md/#check-logs) and send it to the support team.\n\n## Asterisk: The popup window is not displayed\n\nTo be able to make / receive calls with the popup window, check these items:\n\n1. If Asterisk server is properly [configured](asterisk-integration-setup.md#step-1).\n2. If cron job is [configured](asterisk-integration-setup.md#step-2).\n3. If internal users are [configured](asterisk-integration-setup.md#how-to-setup-asterisk-integration-for-users). In some cases, Asterisk server doesn't provide internal number, but you can add other user numbers in his [profile](asterisk-integration-setup.md#additional-phone-numbers-for-users).\n4. If your SIP client are running.\n\nNow, you can make calls from SIP client or from EspoCRM.\n\n## Asterisk: Click to call is not working\n\nVoIP Integration extension is sending a request to Asterisk server when you click on a phone number.\nMake sure the following parameters are correct (Administration > VoIP Settings > VoIP » Asterisk AMI):\n1. `Dialout Channel` - it determines the channel for outgoing calls. It can be \"PJSIP/###\" (Asterisk 13+) or \"SIP/###\", where ### is a user’s extension (internal number). The extension \"###\" will be substituted automatically depending on the user.\n\n  ![Dialout Channel](../../_static/images/extensions/voip-integration/troubleshooting-click-to-call-1.png)\n\n2. `Dial Context` - context of your outgoing calls. The default value of Asterisk server is `from-internal`. If you use some custom extension in your Asterisk server, you have to define it in EspoCRM.\n\n  ![Dialout Channel](../../_static/images/extensions/voip-integration/troubleshooting-click-to-call-2.png)\n\n3. `User Dial Context` - each user can define his own Dial Context in his user's profile. Make sure this option is empty or defined correctly.\n\n  ![Dialout Channel](../../_static/images/extensions/voip-integration/troubleshooting-click-to-call-3.png)\n\n4. `Dial Format for outgoing calls` - this option may need to be changed depending on the Asterisk server configuration.\n\n![Dial Format](../../_static/images/extensions/voip-integration/troubleshooting-click-to-call-4.png)\n\n## Starface: The popup window is not displayed\n\nCheck the following items to find the cause of the issue:\n\n1. If Starface integration is properly [configured](starface-integration-setup.md).\n2. If internal users are [configured](starface-integration-setup.md#how-to-setup-starface-integration-for-users).\n3. If your SIP client is running.\n4. If your EspoCRM server is available for the Starface server. This is required, because Starface server should send notifications about call events to EspoCRM server.\n5. If your `Site URL` (Administration > Settings) corresponds to the real one.\n\n## Twilio: Unable to activate the phone number\n\nIn your [Twilio Console](https://www.twilio.com/console) on the left panel click on United States (US1) (or any other country) > Phone Numbers > Manage > Active Numbers > the number you purchased and in the *Voice and Fax* and *Messaging* sections, set the following settings:\n\n![Voice and Fax](../../_static/images/extensions/voip-integration/twilio-voice-and-fax.png)\n\n![Messaging](../../_static/images/extensions/voip-integration/twilio-messaging.png)\n"
  },
  {
    "path": "docs/extensions/voip-integration/twilio-integration-setup.md",
    "content": "# Twilio Integration Setup\n\nTwilio integration is available as part of [VoIP Integration extension](https://www.espocrm.com/extensions/voip-integration/). It allows you to integrate EspoCRM with Twilio service and other VoIP providers, read more details [here](https://www.espocrm.com/features/twilio-integration/).\n\nThere are two ways in which you can set up Twilio integration:\n\n1. **Call forwarding**. An incoming call from a Twilio number is forwarded to the user’s primary phone number. For outgoing calls EspoCRM creates a connection between the user’s primary phone number and the number called through Twilio service. For more details about how you will be charged for these calls, [click here](https://support.twilio.com/hc/en-us/articles/223132367-How-Much-am-I-Charged-for-Call-Forwarding-with-Twilio).\n2. **Twilio SIP Trunk**. A SIP trunk is a virtual version of a phone line, that isn’t physically connected to a phone company and uses intranet and internal communication systems to access the outside phone lines. More detailed information about Twilio SIP Trunking can be found via the [link](https://www.twilio.com/docs/voice/api/sip-interface).\n\n## How to configure Twilio Integration for an administrator\n\n1. Login to your Twilio account. If you have never used Twilio before, then create the account and purchase a phone number if needed.\n2. Login as Administrator in EspoCRM.\n3. Navigate to the Administration (System panel) > Integrations > VoIP · Twilio.\n4. Tick off Enabled box.\n5. Fill in the connection details of your Twilio account.\n\n![Twilio integration config](../../_static/images/extensions/voip-integration/twilio-admin-setup.png)\n\n* **Name** – name of your connection.\n* **Your Account SID** – your Twilio account SID. You can get it at https://www.twilio.com/console.\n* **Your Auth Token** – your Twilio Auth Token. You can get it at https://www.twilio.com/console.\n* **Record Calls** – an option to enable/disable recording of incoming/outgoing calls.\n* **Dial Timeout** – the number of seconds that Twilio will allow the phone to ring before assuming there is no answer.\n* **Agent Ringing Timeout** – the waiting limit in seconds to answer the call by the agent, e.g. for an incoming call each agent will get a ringing duration of 20 seconds.\n* **Assign a Preferred User** – assign a preferred user for incoming calls, sms/mms, e.g. for an incoming call, if the caller is found in EspoCRM, then Twilio will forward the call to the assigned user instead of the routing user list.\n* **Access Key to EspoCRM** – an access key of EspoCRM to post data from Twilio.\n* **Default Country** – the country is used to format phone numbers.\n* **Dial Format for outgoing calls** – a phone number format for outgoing (click-to-call) calls.\n* **Enabled SIP Domains** – the list of enabled Twilio SIP domains which are used in EspoCRM.\n* **List of ignored numbers** – list of numbers which will be ignored. Popup window will not be displayed. Use numbers in the following formats: +14844608117 (full number match) or #4844608117# (regular expression).\n* **Permitted Entities** – entities that will be displayed in the popup window and will be used to identify a caller by his phone number.\n* **Apply global ACL for caller lookup** – apply global ACL rules (Administration > Roles) for caller lookup. This information is displayed in the popup window. If unchecked, no ACL restrictions are used.\n* **Hide a Lead** – Hide a Lead in a call popup when Account / Contact are available.\n* **Display Accounts related to Contacts** – display only Accounts related to Contacts.\n* **Automatically save a call** – automatically save incoming/outgoing calls without having to press “Save” button.\n* **Automatically open the caller information** – automatically open the caller information for incoming/outgoing calls.\n* **Quick Create Entities** – entities which can be created through the call popup window.\n* **Call Transfer Entities** – the list of entities used for call transfer.\n* **Transfer Timeout** – the number of seconds the customer has to wait for an agent to answer the transferred call.\n* **Experimental features** – test experimental features.\n\n## How to configure routing of Twilio phone numbers\n\nAfter you have successfully filled in the connection details, EspoCRM will import all active Twilio phone numbers (wait a few minutes the first time).\n\n1. **Configure Routing**\n\n    To configure Twilio phone number routing, go to Administration > VoIP Trunks and select the phone number.\n\n    ![Twilio Routers](../../_static/images/extensions/voip-integration/twilio-routing.png)\n\n* **Assigned Team** – a list of responsible users for the line.\n* **Status** – an option to enable/disable the phone number in EspoCRM (in Twilio it will stay active).\n* **For SMS** – default assignment for SMS, only if the sender is not found in EspoCRM.\n* **For MMS** – default assignment for MMS, only if the sender is not found in EspoCRM.\n* **For Missed Call** – a team member who will receive voicemail messages.\n* **Greeting at the beginning of the call**\n* **Voicemail**\n* **Voicemail Greeting Audio** – .mp3 or .wav voicemail greeting file.\n* **Voicemail Greeting Text** – a voicemail greeting message. Note: the “Voicemail Greeting Audio” has higher priority.\n* **Voicemail Notifications** – Types of notification for a new voicemail message.\n* **Farewell at the end of the call**\n* **Display the router's phone number as a caller** – display the office phone number (VoIP Router phone number) as caller.\n* **Team Users** – a list of users to configure receiving incoming/outgoing calls, SMS and MMS.\n\n2. **Grant access for Twilio Team members**\n\n    Go to Administration > Roles, create a Role for a Team of Twilio members (defined above) and grant access to the following entities: Calls, Messages, Accounts, Contacts, Leads.\n\n## How to configure Messages (SMS, MMS)\n\n1. Enable Twilio messaging geographic permissions:\n    1. Login to your Twilio account.\n    2. Navigate to the Programmable SMS > Settings > Geo Permissions or just click the link: https://www.twilio.com/console/sms/settings/geo-permissions.\n    3. Enable needed countries.\n2. [Grant access to Messages](customization.md#grant-access-to-messages)\n\n## How to setup Twilio Integration for users\n\nEach user has to add his phone number which will be used to handle incoming calls. It can be added in the User’s Profile.\n**Note**: If you are using a Twilio SIP, then instead of the phone number, you have to specify the SIP number in the format: “agent1@YOUR_DOMAIN.sip.twilio.com”.\n\n![Phone numbers formats](../../_static/images/extensions/voip-integration/twilio-user-phone.png)\n\nAll other configuration settings should be made by your administrator. The user can change some VoIP settings in his User’s Profile, under “VoIP Settings”.\n\n![VoIP settings](../../_static/images/extensions/voip-integration/twilio-user-setup.png)\n\n* **VoIP Server** – your current VoIP server.\n* **Your user extension** – Twilio phone number configured by the administrator .\n* **Display call notifications** – an option to enable/disable incoming/outgoing call notifications.\n* **Silent notifications** – mute notification sound.\n* **Use internal click-to-call** – an option to enable/disable the internal click-to-call feature. It is a feature to make outgoing calls through Twilio. If the checkbox is unchecked, then an external application will handle “tel:” links.\n\n## Access control for users\n\nMake sure that your users have the access to the entity 'Calls'.\n\n* [Grant access to Calls](customization.md#grant-access-to-calls)\n\n## How to configure SIP Domains\n\n1. Configure a SIP domain in Twilio:\n\n    1. Login to your Twilio account.\n    2. Go to Twilio SIP Domains by clicking in the menu on the left side and select “Programmable Voice” option or just click the link: https://www.twilio.com/console/voice/sip/endpoints.\n\n    ![Twilio SIP Domains](../../_static/images/extensions/voip-integration/twilio-sip-domains.png)\n\n    3. The next thing to do is to create a SIP Domain. To do that, select Domains option in the menu on the left side and press “+” button.\n\n    ![Twilio add SIP domains](../../_static/images/extensions/voip-integration/twilio-add-sip-domain.png)\n\n    4. In the next window, you have to set up the domain configuration. Set the domain name (Friendly name), create your custom SIP URL, create Credential list for Voice Authentication, enable SIP Registration (by default its disabled), select Credential lists (created for Voice Authentication) and click Save.\n\n    ![Twilio SIP configuration](../../_static/images/extensions/voip-integration/twilio-sip-domain-configuration.png)\n\n2. Enable this SIP Domain in EspoCRM connector:\n\n    1. Login as Administrator in EspoCRM.\n    2. Navigate to the Administration > VoIP Settings > VoIP » Twilio.\n    3. Select your custom SIP URL from the “Enable SIP Domains” field.\n\n    ![Twilio enable SIP domain](../../_static/images/extensions/voip-integration/twilio-enable-sip-domain.png)\n\n## More Twilio settings for users\n\nEach user can set “Do Not Disturb” mode for incoming lines. To do it, go to the home page (click on a logo) and add a “VoIP Settings” dashlet (“+” button).\n\n![Twilio dashlet](../../_static/images/extensions/voip-integration/twilio-dashlet.png)\n"
  },
  {
    "path": "docs/extensions/zoom-integration/index.md",
    "content": "# Zoom Integration\n\n*Requires EspoCRM v9.0.*\n\nAvailable in the [Zoom Integration](https://www.espocrm.com/extensions/zoom-integration/) extension.\n\nThe Zoom integration allows creating Zoom meetings from Espo.\n\nIn this article:\n\n* [How it works](#how-it-works)\n* [Connecting Zoom accounts](#connecting-zoom-accounts)\n* [Setting up](#setting-up)\n* [Usage](#usage)\n\n## How it works\n\nYou need to have one general Zoom account (organization account). This account will be connected to Espo. Espo users need to have their Zoom accounts linked to the general Zoom account. The Espo administrator will select which users can use Zoom integration.\n\nWhen an Espo meeting is pushed to Zoom, it's created in a Zoom account of the user assigned to the meeting. If the user does not have a Zoom account, it won't be possible to push the meeting.\n\n## Connecting Zoom accounts\n\nConnect Zoom accounts of your employees to the organization Zoom account.\n\nTo connect a user:\n\n1. Log in to Zoom Admin as an admin.\n2. Go to User Management > Users.\n3. Click Add Users and enter the user's email address.\n4. Check Zoom Meetings Basic for the user.\n5. Send an invitation, and the user must accept it to join your Zoom account.\n\n## Setting up\n\nAs an Espo administrator, go to: Administration > Integrations > Zoom. Then, follow the guidelines displayed on the page.\n\n1. Create a General App on the Zoom App Marketplace. Set it as Admin-managed.\n2. Obtain the Client ID and Client Secret.\n3. Copy the Redirect URI from here and add it in the created Zoom app.\n4. Add the required scopes in the Zoom app.\n5. Connect.\n\nRequired scopes:\n\n* `meeting:write:meeting:admin`\n* `meeting:update:meeting:admin`\n* `meeting:delete:meeting:admin`\n\nThere are Development and Production modes for Zoom apps. They use different credentials. It's recommended to use the Production mode unless for testing purposes.\n\nIf you use the Production mode, you will also need to fill in the required fields:\n\n* App Name\n* Developer Contact Information\n* Scope Description\n\nThen, the Zoom App will be marked as *Ready for beta test* in the right panel. Otherwise, you won't be able to connect to a production mode app.\n\n\n!!! note\n\n    There is no need to publish the Zoom App.\n\n\nAfter connecting to Zoom in Espo, on the same page, select users who are supposed to receive Espo meetings in their Zoom accounts.\n\nThe primary email address of a user is used as their Zoom ID by default. You can also specify the Zoom ID for a particular user.\n\nTo allow users to push Espo meetings to Zoom, you need to enable the *Zoom Meetings* scope in roles of those users.\n\n\n## Usage\n\nTo be able to push a meeting to Zoom, a user needs to have:\n\n* access to the *Zoom Meetings* scope;\n* edit access the meeting.\n\nTo push the meeting, click *Push to Zoom* from the dropdown next to the *Edit* button.\n\nOnce a Zoom meeting is created, the Join URL field in the Espo meeting will be set to the Zoom's URL.\n\nIf you edit an already pushed meeting in Espo, it will be marked as out-of-sync. You can push it again so that it will become synced with Zoom.\n\nIf an Espo meeting has status *Not Held*, you can delete the corresponding Zoom meeting by clicking *Delete from Zoom*.\n\n### Join URL\n\nThe *Join URL* field is the default Espo field. You can add to the Meeting's layout under: Administration > Entity Manager > Meeting > Layouts > Detail.\n\nWhen sending an email invitation from Espo, the Join URL will be included in the email body. You can edit the email template under Administration > Template Manager > Invitation · Meeting.\n\n### Meeting scheduler\n\nThe Zoom integration is integrated with the [Meeting Scheduler](../meeting-scheduler/index.md). You can specify Zoom as the online location for a specific scheduler.\n\n### Workflows\n\nIt's possible to create and delete zoom meetings using a [Workflow](../../administration/workflows.md) rule. Actions are available under *Run Service Action* for a Meeting target.\n"
  },
  {
    "path": "docs/index.md",
    "content": "# EspoCRM Documentation\n\n### Administration\n\n* Server configuration\n  * [Configuration](administration/server-configuration.md)\n  * [Apache](administration/apache-server-configuration.md)\n  * [Nginx](administration/nginx-server-configuration.md)\n  * [IIS](administration/iis-server-configuration.md)\n* System\n  * Installation\n    * [Installation](administration/installation.md)\n    * [Installation by script](administration/installation-by-script.md)\n    * [Installation with Docker](administration/docker/installation.md)\n    * [Installation with Traefik](administration/docker/traefik.md)\n    * [Installation with Caddy](administration/docker/caddy.md)\n  * [Upgrading](administration/upgrading.md)\n  * [Extensions](administration/extensions.md)  \n  * [Jobs](administration/jobs.md)\n  * [Config parameters](administration/config-params.md)\n  * [Log](administration/log.md)\n  * [Console commands](administration/commands.md)\n  * [WebSocket](administration/websocket.md)\n* Essentials\n  * [Terms & naming](administration/terms-and-naming.md)\n  * [Troubleshooting](administration/troubleshooting.md)\n  * [Backup and restore](administration/backup-and-restore.md)\n  * [Performance tweaking](administration/performance-tweaking.md)\n  * [Moving to another server](administration/moving-to-another-server.md)\n  * [Security](administration/security.md)\n* Customization\n  * [Entity Manager: entities, fields, relationships](administration/entity-manager.md)\n  * [Fields](administration/fields.md)\n  * [Layouts](administration/layout-manager.md)\n  * [Dynamic Logic](administration/dynamic-logic.md)\n  * [API Before-Save script](administration/api-before-save-script.md)\n* [Users](administration/users-management.md)\n* [Roles](administration/roles-management.md)\n* [Email administration](administration/emails.md)\n* Formula\n  * [Formula script](administration/formula.md)\n  * [Functions](administration/formula-functions.md)\n* [Import](administration/import.md)\n* [Portal](administration/portal.md)\n* [Web-to-Lead](administration/web-to-lead.md)\n* [Currency](administration/currency.md)\n* [Dashboards](administration/dashboards.md)\n* Authentication\n  * [2-factor authentication](administration/2fa.md)\n  * [OpenID Connect](administration/oidc.md)\n  * LDAP\n    * [Authorization](administration/ldap-authorization.md)\n    * [Active Directory](administration/ldap-authorization-for-ad.md)\n    * [OpenLDAP](administration/ldap-authorization-for-openldap.md)\n* Miscellaneous\n  * [Webhooks](administration/webhooks.md)\n  * [Passwords](administration/passwords.md)\n  * [Security](administration/security.md)\n  * [Phone numbers](administration/phone-numbers.md)\n  * [Addresses](administration/addresses.md)\n  * [Maps](administration/maps.md)\n  * [B2C mode](administration/b2c.md)\n  * [Collaborators](administration/collaborators.md)\n  * [Multiple assigned users](administration/multiple-assigned-users.md)  \n  * [File storage](administration/file-storage.md)\n  * [SMS sending](administration/sms-sending.md)\n  * [App secrets](administration/app-secrets.md)\n\n---\n\n### User Guide\n\n* Emails\n  * [General guidelines](user-guide/emails.md)\n  * [IMAP & SMTP configuration](user-guide/imap-smtp-configuration.md)\n  * [Mass email](user-guide/mass-email.md)\n* [Stream](user-guide/stream.md)\n* [Sales management: Leads & Opportunities](user-guide/sales-management.md)\n* [Case management](user-guide/case-management.md)\n* [Activities & calendar](user-guide/activities-and-calendar.md)\n* [Campaigns](user-guide/campaigns.md)\n* [Mail merge (mass snail mailing)](user-guide/mail-merge.md)\n* [Knowledge base](user-guide/knowledge-base.md)\n* [Documents](user-guide/documents.md)\n* [Export](user-guide/export.md)\n* [Text search](user-guide/text-search.md)\n* [Working time calendar](user-guide/working-time-calendar.md)\n* [Printing to PDF](user-guide/printing-to-pdf.md)\n* Miscellaneous\n  * [Shortcut keys](user-guide/shortcuts.md)\n  * [Markdown syntax](user-guide/markdown.md)\n  * [Browser support](user-guide/browser-support.md)\n  * [Data privacy](user-guide/data-privacy.md)\n  * [Complex expressions](user-guide/complex-expressions.md)\n  * [Optimistic concurrency control](user-guide/optimistic-concurrency-control.md)\n\n---\n\n### Extensions\n\n* Advanced Pack\n  * [Overview](extensions/advanced-pack/overview.md)\n  * [Reports](user-guide/reports.md)\n  * [Workflows](administration/workflows.md)\n  * [Business Process Management (BPM)](administration/bpm.md)\n* Sales Pack\n  * [Overview](extensions/sales-pack/overview.md)\n  * [Products](user-guide/products.md)\n  * [Prices](extensions/sales-pack/prices.md)\n  * Sales\n    * [Quotes](user-guide/quotes.md)\n    * [Sales Orders](user-guide/sales-orders.md)\n    * [Invoices](user-guide/invoices.md)\n    * [Credit Notes](extensions/sales-pack/credit-notes.md)\n    * [Delivery Orders](extensions/sales-pack/delivery-orders.md)\n    * [Return Orders](extensions/sales-pack/return-orders.md)\n    * [Write-offs](extensions/sales-pack/write-offs.md)\n    * [Subscriptions](extensions/sales-pack/subscriptions.md)\n  * Purchases\n    * [Suppliers](extensions/sales-pack/suppliers.md)\n    * [Purchase Orders](extensions/sales-pack/purchase-orders.md)\n    * [Receipt Orders](extensions/sales-pack/receipt-orders.md)\n    * [Bills](extensions/sales-pack/bills.md)\n    * [Bill credits](extensions/sales-pack/bill-credits.md)    \n  * [Inventory Management](extensions/sales-pack/inventory-management.md)\n  * [Payments](extensions/sales-pack/payments.md)\n  * [Taxes](extensions/sales-pack/taxes.md)\n  * [Tax codes](extensions/sales-pack/tax-codes.md)\n  * [Issuance locking](extensions/sales-pack/issuance-locking.md)\n  * [Multi-currency](extensions/sales-pack/multi-currency.md)\n  * [Reports](extensions/sales-pack/reports.md)\n* Project Management\n  * [Projects](extensions/project-management/projects.md)\n* Meeting Scheduler\n  * [Meeting Scheduler](extensions/meeting-scheduler/index.md)\n* Google Integration\n  * [Setting-up](extensions/google-integration/setting-up.md)\n  * [Calendar](extensions/google-integration/calendar.md)\n  * [Contacts](extensions/google-integration/contacts.md)\n  * [Gmail](extensions/google-integration/gmail.md)\n* Outlook Integration\n  * [Setting-up](extensions/outlook-integration/setting-up.md)\n  * [Calendar](extensions/outlook-integration/calendar.md)\n  * [Contacts](extensions/outlook-integration/contacts.md)\n  * [Email](extensions/outlook-integration/email.md)\n* VoIP Integration\n  * [Overview](extensions/voip-integration/overview.md)\n  * [3CX PBX](extensions/voip-integration/3cx-integration-setup.md)\n  * [Twilio service](extensions/voip-integration/twilio-integration-setup.md)\n  * [Asterisk server](extensions/voip-integration/asterisk-integration-setup.md)\n  * [Starface server](extensions/voip-integration/starface-integration-setup.md)\n  * [Binotel service](extensions/voip-integration/binotel-integration-setup.md)\n  * [IexPBX server](extensions/voip-integration/iexpbx-integration-setup.md)\n  * [Docker container](extensions/voip-integration/docker-container.md)\n  * [Customization](extensions/voip-integration/customization.md)\n  * [Troubleshooting](extensions/voip-integration/troubleshooting.md)\n* Zoom Integration\n  * [Zoom Integration](extensions/zoom-integration/index.md)\n* Stripe Integration\n  * [Stripe Integration](extensions/stripe-integration/index.md)\n* Export Import\n  * [Overview](extensions/export-import/overview.md)\n  * [Export](extensions/export-import/export.md)\n  * [Import](extensions/export-import/import.md)\n  * [Compare](extensions/export-import/compare.md)\n  * [Run by code](extensions/export-import/run-by-code.md)\n  * [Customization](extensions/export-import/customization.md)\n\n---\n\n### See also\n\n* [Developer documentation](development/index.md)\n* [Hints & tips](https://www.espocrm.com/tips/)\n"
  },
  {
    "path": "docs/js/extra.js",
    "content": "document.addEventListener(\"DOMContentLoaded\", function() {\n    loadNavpanel();\n});\n\nfunction loadNavpanel() {\n    var width = window.innerWidth;\n    if (width <= 1200) {\n        return;\n    }\n\n    var activeEls = document.getElementsByClassName('md-nav__item--active');\n\n    for (var i = 0; i < activeEls.length; i++) {\n        var navEl = activeEls.item(i);\n        var toggleEl = navEl.getElementsByClassName('md-nav__toggle')[0] || null;\n        if (toggleEl) {\n            toggleEl.checked = true;\n        }\n    }\n}\n"
  },
  {
    "path": "docs/user-guide/activities-and-calendar.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Activities & Calendar\n\nThere are three types of activities available in EspoCRM by default:\n\n* Meetings\n* Calls\n* Tasks\n\nAn administrator can create a custom entity type of an *Event* type. Then, at Administration > Settings > Activities, it's possible to set this entity type as an *Activity* and make it available in the *Calendar*.\n\nThe *My Activities* dashlet displays current and upcoming activity records associated with the current user.\n\nAccounts, Contacts, Leads, Opportunities, and Cases have the Activities panel on the detail view. Custom entity type of the *Base Plus* type have the Activities panel as well.\n\nIn this article:\n\n* [Meetings & Calls](#meetings-calls)\n* [Tasks](#tasks)\n* [Calendar](#calendar)\n\n## Meetings & Calls\n\n### Attendees\n\nThere are 3 types of attendees: Users, Contacts, and Leads. For each attendee, it's possible to specify acceptance status: Accepted, Tentative or Declined.\n\n#### Invitations\n\nThere is the ability to send **invitation emails** to attendees by clicking the button in the top-right corner. Attendees will be able to set their acceptance status by clicking on a corresponding link in the email. \n\nWhen an event has status *Not Held*, it's possible to send a cancellation email to attendees. It can be done from the top-right menu on the Meeting (or Call) detail view.\n\nThe template for invitation emails can be changed at Administration > Template Manager > Invitation.\n\nAvailable template placeholders and data values:\n\n* `inviteeName` – a name of the recipient;\n* `recordUrl` – a URL to the Espo meeting record;\n* `acceptLink` – a URL to accept the meeting;\n* `declineLink` – a URL to decline the meeting;\n* `tentativeLink` – a URL to set as tentative;\n* `entityType` – a translated entity type (Meeting or Call);\n* `entityTypeLowerFirst` – a translated entity type starting with a lower case letter (meeting or call);\n* `isUser` – whether the recipient is a User, a boolean value;\n* `dateStartFull` – a meeting start date/time in full format (as of v9.0);\n* `timeZone` – a time zone name applied to date-time placeholder values (as of v9.0).\n\nYou can also use Meeting's (or Call's) fields as placeholders.\n\n### Reminders\n\nThere are two types of reminders: Popup and Email. Reminders specified on the form will be applied to the current user, assuming this used is a participant. Other participant will have their default reminders automatically applied.\n\n!!! note\n\n    When creating a Meeting or Call, only the reminder options that will occur in the future are listed. For example, if you create a meeting scheduled to occur in 15 minutes, you won't be able to set a reminder for '1 hour before'. This option won't be available in the list. If you change the Date Start to a later time, the option will appear.\n\nArbitrary period values can entered in the reminder field by typing a number.\n\n### Default duration\n\nDefault duration can be changed by the administrator at Administration > Entity Manager > Meetings / Calls > Fields > Duration > Default. It is specified in seconds.\n\n### Scheduler\n\nThe scheduler panel provides the ability to view free & busy time ranges for user attendees when creating or editing an event. Available for Meetings, Calls, and custom entities of the Event type.\n\nThe scheduler panel can be added or removed at Administration > Entity Manager > Layouts > {Entity Type} > Bottom Panels.\n\nWhich entity types will be taken into account when showing busy time ranges can be configured at Administration > Settings > Free/Busy Entity List.\n\n### Default date\n\nFor the Meeting and custom Event entity types, by default, the default values for Date Start and Date End are set to 'now'. You can change it to 'today' (meaning the event will be set as All-Day by default). For this, in the Entity Manager, do the following:\n\n1. Set the default values for the Date Start and Date End fields to 'None'.\n2. Set the default values for the Date Start (all day) and Date End (all day) fields to 'Today'.\n3. Set the default value for the Duration field to 86400.\n4. Set the default value for the Is All-Day field to true (check the checkbox).\n\n### Join URL\n\nThe *Join URL* field is available in the Meeting entity type. By-default, it is read-only, but it's possible to make it editable. The field is written by online meeting integrations. The default meeting invitation template includes the Join URL placeholder.\n\n## Tasks\n\nThe Date Start and Date Due fields are not required. Dates can be specified with or without time parts.\n\n### Reminders\n\nThe *Reminders* field is hidden if the *Date Due* field is empty. It will show up once it's filled in.\n\n!!! note\n\n    When the Date Due does not have a time part, the end of the day will be used as the base time for a reminder.\n\nArbitrary period values can entered in the reminder field by typing a number.\n\n### Collaborators\n\n*As of v9.0.*\n\nThe [collaborators](../administration/collaborators.md) feature is enabled for Tasks by default.\n\nUsers added as collaborators to a Task obtain read and stream access, provided their access level, as defined by Roles, is other than no.\n\nWhen a user creates a Task, they are automatically added as a collaborator, even if the Task is assigned to another user. The assignee becomes a collaborator too.\n\nThe list view filter *Shared* shows Tasks where the current user is a collaborator. The *My Activities* dashlet has a parameter *Include Shared*.\n\n## Calendar\n\nCalendar displays Meetings, Calls, and Tasks. It's also possible to show custom entities of the Event type.\n\nSupported views:\n\n* Month\n* Week\n* Day\n* Timeline\n\nUsers can also add the Calendar to their dashboard.\n\nIt's possible to view the calendar of another user (is you have an access determined by Roles). The *Calendar* button is available on the user's detail view.\n\n### Refreshing calendar\n\nTo refresh calendar items, you can click on the date range title at the top in the center.\n\n### Shared calendar\n\nUsers can create custom shared views that will display events of specific teams.\n\n!!! note\n\n    A user must have a proper *User Permission* set in [Roles](../administration/roles-management.md) to be able to use shared calendars. Set the permission to *team* or *all* to enable.\n\n!!! note\n\n    The Shared view displays events of users of a selected team. It doesn't necessary display events assigned to that team (e.g. event is assigned to the team, but doesn't assigned to any user of that team).\n\nThe Shared view is also available for the *Timeline* view. It allows you to view events of multiple users.\n\n### Custom entities on calendar\n\nAn administrator can create a custom entity of the Event type. Then, at Administration > Settings > Activities, it's possible to set this entity type as an Activity and make it available in Calendar.\n\nFor custom entities, by default, the *Assigned User* field determines a user who will see the record on they Calendar. There is the ability to have [multiple assigned users](../administration/multiple-assigned-users.md).\n\n## See also\n\n* [Working time calendar](working-time-calendar.md)\n* [Calendar & Activities quick tour](https://app.supademo.com/demo/cmj2mit950x3tv3e5ae3xp6fa)\n* [How to manage your calendar](https://www.espocrm.com/tips/calendar/)\n* [Meeting scheduler](../extensions/meeting-scheduler/index.md)\n"
  },
  {
    "path": "docs/user-guide/browser-support.md",
    "content": "# Browser support\n\nWe recommend using the latest versions of Google Chrome or Mozilla Firefox. We regularly test in these browsers.\n\nMicrosoft Edge and Safari are also supported, but there are less guarantees that everything will be working smoothly.\n"
  },
  {
    "path": "docs/user-guide/campaigns.md",
    "content": "# Campaigns\n\nCampaigns help you create and manage various marketing initiatives, including email, newsletters, web, radio, television, and direct mail.\n\nThe *Type* field in a campaign record has the following options:\n\n- Email. Mass email marketing.\n- Newsletter. Mass newsletter email.\n- Information Email. Mass email of non-marketing nature, for example, information about a license update.\n- Web\n- Television\n- Radio\n- Mail. Direct mail.\n\nLeads, Opportunities, Accounts, and Contacts can be associated with a campaign. When a lead is created for a specific campaign, a *Lead Created* entry is added to the campaign log.\n\nA [Lead Capture](../administration/web-to-lead.md) can be associated with a specific campaign. All generated leads will then be linked to that campaign.\n\nSee also:\n\n- [Mass email](mass-email.md)\n- [Mail merge](mail-merge.md)\n- [Campaigns quick tour](https://app.supademo.com/demo/cmnim3kjr01wvwn0j4g5jug04)\n\n## Target lists\n\nTarget lists can be specified for campaigns Email, Newsletter, Information Email, and Mail campaigns. The *Target Lists* field defines the target audience, while the *Excluding Target Lists* field specifies who to exclude. Contacts in the excluding list are excluded, even if they appear in the campaign's target list.\n\n## Log\n\nLog entries display activity history of the campaign. The following events are logged:\n\n- Sent. An email is sent (mass email).\n- Opened. A recipient opened an email (mass email).\n- Opted Out. A recipient unsubscribed (mass email).\n- Opted In. A recipient subscribed back (mass email).\n- Bounced. An email is bounced (mass email). Can be hard and soft bounced.\n- Clicked. A recipient clicked a tracking URL (mass email).\n- Lead Created. Anew lead associated with the campaign is created.\n\n## Statistics\n\nThe Statistics panel in a campaign displays the following metrics:\n\n- Sent. The total number of emails sent within the campaign (mass email).\n- Clicked. The total number of clicks on tracking URLs within the campaign.\n- Opted Out. The total number of recipients who opted out and percentage.\n- Bounced. The total number of bounced emails and percentage.\n- Lead Created. The total number of created leads.\n- Opted In. The total number of recipients who opted in back and percentage.\n- Revenue. Calculated by summing up all associated *Closed Won* opportunities.\n"
  },
  {
    "path": "docs/user-guide/case-management.md",
    "content": "# Case Management\n\nIn this article:\n\n* [Overview](#overview)\n* [Stream](#stream)\n* [Email-to-case](#email-to-case)\n* [Knowledge base](#knowledge-base)\n* [Customer portal](#customer-portal)\n* [Access to child records](#access-to-child-records)\n* [Collaborators](#collaborators)\n* [See also](#see-also)\n\n## Overview\n\nCases provide issue-tracking capabilities and a key aspect of customer service in EspoCRM. The term 'ticket' can also be used to refer to Cases.\n\nNew Cases are supposed to be created in the following scenarios:\n\n* Manually by CRM users;\n* Manually by users of a customer portal;\n* Through the API (e.g. through a web form;\n* Automatically when a new email comes to a specific mailbox;\n* Automatically by a Workflow rule.\n\nWhen a new Case is created by a Portal User, it's not assigned to any user. By utilizing the [Workflows](../administration/workflows.md) tool, an administrator can create a rule that will notify certain users about every new Case in the system. Workflows also provide the ability to apply an assignment rule to new cases. *Round-Robin* and *Least-Busy* rules are available. For more complex business flows, it's recommended to utilize the [BPM tool](../administration/bpm.md).\n\nTo prevent overlooking of new Cases, users can add the Case entity type to the *Global Auto-follow* list in the user's Preferences. Then, the user will automatically follow every new Case created in the system they have access to.\n\nThe Case entity type can be associated with one Account and/or multiple Contacts. It also can be associated with a Lead record. Note that by default the Lead field is not available in the Detail layout. An administrator can add it at: Administration > Entity Manager > Case > Layouts > Detail.\n\n!!! note\n\n    If a related Contact is not associated with a Portal User, then the customer won't be receiving email notifications about updates in the Stream of te Case. In this scenario, you need to use emails for communication with the customer.\n\n!!! tip\n\n    Cases are not necessarily limited to customer service purposes. You can also use them to track non-support-related topics.\n\n## Stream\n\nA Case record has a Stream that can be used for communication between the customer and the support team.\n\nCRM users can mark stream posts as *internal*. Such posts are not visible in the customer portal and the customer is notified about them. To make a post internal, click the *lock* icon next to the *Post* button before posting.\n\n## Email-to-case\n\nAn administrator can set up a Group Email Account that will create a new Case on each incoming email. For more information, [see here](../administration/emails.md).\n\nUsers can create Cases from Emails manually. On the Email detail view, click the dropdown in the top-right corner, then *Create Case*.\n\nWhen a user wants to send a reply to a customer, they need to make sure that the Case is selected as a *Parent* of the Email that is being composed. This will force automatical addition of the group email address to the *Reply-To* field of the email. Then, when the customer replies on that email, it will be sent to the group email address rather than to the user’s one.\n\n## Knowledge base\n\nUsers can relate Knowledge Base Articles to a Case record. See more info about the Knowledge Base [here](knowledge-base.md).\n\n## Customer portal\n\nAn administrator can create a [Portal](../administration/portal.md) where customers will be able to create Cases. Permission to create Cases can be granted in a Portal Role.\n\nSince Portal Users automatically follow Cases they have created, they will receive email notifications about new messages in the case's stream. Notifications are sent from the system email account. So when a customer replies to a notification, it will be sent to the system email address. It's also possible to make email replies to go to a Group Email Account. For this, you need to utilize the Workflow tool (or Formula) to make all new cases be automatically linked with the Group Email Account (use the Update Target Record action, set the *Group Email Account* field).\n\nCases marked is *Hidden from Portal* are not available in portals. It can be useful when referencing a Contact is needed but the customer should not have access to the Case. As of v9.0.\n\n## Access to child records\n\nUser access to child records of a Case, such as Emails, Meetings and Calls, is not determined by access to the Case record. For example, a Case can be assigned to a User but a related Email is not related to that User resulting in the User not being able to view the Email.\n\nBy utilizing the Workflow tool, it's possible to write a rule that will automatically add the Assigned User of a Case to all child records. The same is also possible with the Teams fields.\n\n## Collaborators\n\n*As of v9.0.0.*\n\nThe collaborators feature can be enabled for Cases at Administration > Entity Manager > Case > Edit. Then, the *Collaborators* field will be automatically created for the Case entity type. You can add this field to the *Side Panel Fields* layout.\n\nUsers added as collaborators to a Case will have read and stream access, provided their access level, as defined by Roles, is other than no.\n\nWhen a user creates a Case, they will be automatically added as a collaborator, even if the Case is assigned to another user. The assignee becomes a collaborator too.\n\n## See also\n\n* [Cases quick tour](https://app.supademo.com/demo/cmmklgg7o227kqfzsariqw6tg)\n* [Notifying contacts about new post in Case with Workflows](https://www.espocrm.com/blog/notifying-contacts-about-new-post-in-case-with-workflows/)\n"
  },
  {
    "path": "docs/user-guide/complex-expressions.md",
    "content": "# Complex expressions\n\nComplex expressions are used to define SQL expressions. Complex expressions are converted into SQL code in run-time.\n\nWhere complex expressions can be utilized:\n\n* in report filters;\n* when working with ORM to avoid writing raw SQL (for developers)\n\n!!! note \"Note for developers\"\n\n    It's possible to build expressions with `Espo\\ORM\\Query\\Part\\Expression` class. See [here](../development/orm.md#complex-expressions).\n\nIn this article:\n\n* [Functions](#functions)\n* [Attribute names](#attribute-names)\n\n## Functions\n\nFunction names should be in UPPER_CASE. You need to append a trailing colon character to a function name. There should not be any whitespace between function name and parentheses.\n\n!!! example \"Examples\"\n\n    ```\n    CONCAT:(firstName, ' ', lastName)\n    ```\n\n    ```\n    IF:(EQUAL:(status, 'Complete'), 'Complete', 'Not Complete')`\n    ```\n\nFunctions:\n\n* [Conditional](#conditional)\n* [Comparison](#comparison)\n* [Date & time](#date-time)\n* [String](#string)\n* [Math](#math)\n* [Logical](#logical)\n* [Misc](#misc)\n\n\n### Conditional\n\n#### IF\n\nE.g. `IF:(a, '1', '0')` – if *a* is true, then return '1'; return '0' otherwise.\n\n#### SWITCH\n\n*As of v7.4.*\n\nAn equivalent of 'CASE WHEN ... THEN ... ELSE ... END'. Arguments on even-numbered positions define 'WHEN' conditions, while following arguments define corresponding 'THEN' values. The last unmatched argument defines 'ELSE'.\n\nE.g. `SWITCH:(EQUAL:(monthNumber, 1), 'Jan', EQUAL:(monthNumber, 2), 'Feb', EQUAL:(monthNumber, 3), 'Mar', 'Other')`.\n\n#### MAP\n\n*As of v7.4.*\n\nAn equivalent of 'CASE ... WHEN ... THEN ... ELSE ... END'. Arguments on odd-numbered positions define keys, while following arguments\ndefine mapped values. The last unmatched argument defines 'ELSE'.\n\nE.g. `MAP:(monthNumber, 1, 'Jan', 2, 'Feb', 3, 'Mar', 'Other')`.\n\n### Comparison\n\n#### LIKE\n\nPattern matching.\n\nE.g. `LIKE:(name, 'Cloud%'`) will give true when 'name' is equal to 'Cloud Basic' or 'Cloud Enterprise'.\n\n#### NOT_LIKE\n\nNegation of LIKE.\n\n#### EQUAL\n\nCheck whether two arguments are equal.\n\nE.g. `EQUAL:(status, 'Complete')` corresponds to SQL statement `status = 'Complete'`.\n\n#### NOT_EQUAL\n\nNegation of equal.\n\n#### GREATER_THAN\n\nCheck whether a > b.\n\nE.g. `GREATER_THAN:(amountConverted, 1000.00)` corresponds to SQL statement `amountConverted > 100.00`.\n\n#### LESS_THAN\n\nCheck whether a < b.\n\n#### GREATER_THAN_OR_EQUAL\n\nCheck whether a >= b.\n\n#### LESS_THAN_OR_EQUAL\n\nCheck whether a <= b.\n\n#### IS_NULL\n\nCheck whether value is NULL.\n\nE.g. `IS_NULL:(sicCode)` – checks whether Sic Code field is not set.\n\n#### IS_NOT_NULL\n\nNegation of IS_NULL.\n\n#### IN\n\nCheck whether a value is within a set of values.\n\nE.g. `IN:(stage, 'Closed Won', 'Closed Lost')` will return true if stage is 'Closed Won' or 'Closed Lost'.\n\n#### NOT_IN\n\nNegation of IN.\n\n#### COALESCE\n\nReturns the first non-NULL value in the list.\n\nE.g. `COALESCE:(dateStart, createdAt)` will return value of createdAt if *dateStart* is not set.\n\n#### IFNULL\n\nIf the first argument is not NULL, it returns it; otherwise it returns the second argument.\n\nE.g. `IFNULL:(name, '')` will return empty string if *name* is NULL.\n\n#### NULLIF\n\nIf the first argument equals the second, returns NULL, otherwise returns the first argument.\n\nE.g. `NULLIF:(name, '')` will return NULL if *name* is empty string.\n\n#### GREATEST\n\n*As of v7.4.*\n\nReturns the max value from a list of expressions.\n\n#### LEAST\n\n*As of v7.4.*\n\nReturns the min value from a list of expressions.\n\n### Date & time\n\n#### MONTH_NUMBER\n\nMonth number. From 1 to 12.\n\n#### WEEK_NUMBER_0\n\nWeek number. Sunday is a first day of week.\n\n#### WEEK_NUMBER_1\n\nWeek number. Monday is a first day of week.\n\n#### DAYOFWEEK\n\nNumber from 1 to 7.\n\n#### DAYOFMONTH\n\nNumber from 1 to 31.\n\n#### YEAR\n\nYear number.\n\n#### YEAR_X\n\nFiscal year number, where X is a number (between 0 and 11) of the fiscal year start. E.g. `YEAR_3`.\n\n#### HOUR\n\nNumber from 0 to 23.\n\n#### MINUTE\n\nNumber from 0 to 59.\n\n#### MONTH\n\nMonth number w/ year. E.g. `2019-05`.\n\n#### QUARTER\n\nQuarter number w/ year. E.g. `2019_1`.\n\n#### QUARTER_X\n\nFiscal quarter number, where X is a number (between 0 and 11) of the fiscal year start. E.g. `QUARTER_3`.\n\n#### WEEK_0\n\nWeek number w/ a year. Sunday is a first day of week.\n\nE.g. `2018/4`.\n\n#### WEEK_1\n\nWeek number w/ a year. Monday as a first day of week.\n\n#### NOW\n\nCurrent date and time.\n\n#### TZ\n\nTime zone conversion.\n\nE.g. `TZ:(createdAt, -10.5)` will apply -10:30 offset.\n\n#### UNIX_TIMESTAMP\n\nUNIX timestamp of a date-time argument or a current timestamp if no argument passed.\n\n#### TIMESTAMPDIFF_YEAR\n\nDifference between two days in years.\n\nE.g. `TIMESTAMPDIFF_YEAR:(createdAt, modifiedAt)`.\n\n#### TIMESTAMPDIFF_MONTH\n\nDifference between two days in months.\n\n#### TIMESTAMPDIFF_WEEK\n\nDifference between two days in weeks.\n\n#### TIMESTAMPDIFF_DAY\n\nDifference between two days in days.\n\n#### TIMESTAMPDIFF_HOUR\n\nDifference between two days in hours.\n\n#### TIMESTAMPDIFF_MINUTE\n\nDifference between two days in minutes.\n\n#### TIMESTAMPDIFF_SECOND\n\nDifference between two days in seconds. Available since v6.0.0.\n\n#### DATE\n\nReturns a date part of a date-time value. Available since v6.0.0.\n\n### String\n\n#### CONCAT\n\nConcatenate. E.g. `CONCAT:(firstName, ' ', lastName)`.\n\n#### LEFT\n\nReturns a specified number of characters from the left of the string. E.g. `LEFT:(someTextColumn, 1000)`.\n\n#### LOWER\n\nConvert to lower case.\n\n#### UPPER\n\nConvert to upper case.\n\n#### TRIM\n\nRemove leading and trailing spaces.\n\n#### CHAR_LENGTH\n\nNumber of characters in string.\n\n#### BINARY\n\nConverts a value to a binary string.\n\n`EQUAL:('test', 'Test')` returns true.\n\n`EQUAL:(BINARY:('test'), 'Test')` returns false.\n\n#### REPLACE\n\nReplaces all the occurrences of a substring within a string.\n\n`REPLACE:('haystack', 'needle', 'replaceWith')`\n\n### Math\n\n#### ADD\n\nAddition. E.g. `ADD:(2, 2)` corresponds to `2 + 2`.\n\n#### SUB\n\nSubtraction. E.g. `SUB:(2, 1)` corresponds to `2 - 1`.\n\n#### MUL\n\nMultiplication. E.g. `MUL:(2, 2)` corresponds to `2 * 2`.\n\n#### DIV\n\nDivision. E.g. `DIV:(2, 4)` corresponds to `2 / 4`.\n\n#### MOD\n\nReturns remainder of a number divided by another number. E.g. `MOD:(6, 4)` corresponds to `6 % 4`.\n\n#### FLOOR\n\nThe largest integer value not greater than the argument.\n\n#### CEIL\n\nThe smallest integer value greater than or equal to the argument.\n\n#### ROUND\n\nRound a number to a specified number of decimal places. E.g. `ROUND:(value, 2)`.\n\n### Logical\n\n#### OR\n\nE.g. `OR:(a, b, c)` corresponds to SQL statement `a OR b OR c`.\n\n#### AND\n\nE.g. `AND:(a, b, c)` corresponds to SQL statement `a AND b AND c`.\n\n#### NOT\n\nE.g. `NOT:(a)` corresponds to SQL statement `NOT a`.\n\n### Misc\n\n#### ANY_VALUE\n\n*As of v9.1.6.*\n\nObtains an arbitrary row from an aggregated group.\n\n### Custom functions\n\nIt is possible to add custom functions. An implementation class name for a custom function should be defined in [metadata](../development/metadata/app-orm.md) by the path app > orm > platforms > {platform} > functionConverterClassNameMap > {function}. The class should implement `Espo\\ORM\\QueryComposer\\Part\\FunctionConverter` interface.\n\n## Attribute names\n\nAttribute names usually are same as system field names. Fields are listed under Administration > Entity Manager > {Entity Type} > Fields.\n\nAttribute names should be in lowerCamelCase.\n\nField types having attributes named differently:\n\n* Link: *fieldId*, *fieldName*.\n* Link-Parent: *fieldId*, *fieldType*.\n* Currency: *field*, *fieldCurrency*.\n\nWhere *field* is the name of the field.\n\nMore info about attributes [here](../administration/terms-and-naming.md#attribute).\n\n"
  },
  {
    "path": "docs/user-guide/data-privacy.md",
    "content": "# Data Privacy\n\nEspoCRM provides the ability to view and erase personal data for specific records.\n\nIn the Entity Manager, an administrator can mark certain fields as those that contain personal data. This option is available for Accounts, Contacts, Leads, and custom entity types of the Person types.\n\nBy default, the following fields are marked as those that can contain personal data.\n\nContacts & Leads:\n\n* Name\n* Email\n* Phone\n* Address\n\nAccounts:\n\n* Email\n\nTo view or erase personal data for a specific record, go to the detail view, then click *View Personal Data* from the dropdown next to the *Edit* button. From there, it's possible to erase certain fields (if the User has edit access).\n\nRegular uses have the ability to view or erase personal data only if they have *Data Privacy* permission (defined in Roles).\n"
  },
  {
    "path": "docs/user-guide/documents.md",
    "content": "# Documents\n\nEspoCRM provides the ability to store documents. By default, the Document entity type has many-to-many relationships with Account, Opportunity, Contact, and Lead. An administrator can create relationships with other entity types.\n\nIn this article:\n\n* [Folders](#folders)\n* [Sending in email](#sending-in-email)\n* [Creating from email attachment](#creating-from-email-attachment)\n* [Uploading in attachments](#uploading-in-attachments)\n* [File types](#file-types)\n* [See also](#see-also)\n\n## Folders\n\nFolders allow to group Documents. Document Folders are presented as a hierarchical tree structure. Each folder can contain sub-folders.\n\nThe Document Folder is a separate entity type. Access to it can be controlled by Roles.\n\n## Sending in email\n\nWhile composing an email, there is the ability to add a certain document as an attachment.\n\n## Creating from email attachment\n\nIt's possible to create a Document from an Email attachment. On the Email detail view from the dropdown at top-right corner, click *Create Document*. The email should have at least one attachment to be able to create a Document from it.\n\n## Uploading in attachments\n\nIt's possible to upload existing Documents directly in Attachment-Multiple fields. This ability can be enabled for a specific field at: Administration > Entity Manager > {Entity Type} > Fields > {your Attachment-Multiple field}. Add *Documents* to the Source List.\n\n## File types\n\nAn administrator can configure allowed file types. Under Administration > Entity Manager > Document > Fields > File, specify allowed file types in the \"Accept\" parameter.\n\n## See also\n\n* [Documents quick tour](https://app.supademo.com/demo/cml9ij9ru1tgyvhwzri4tcrc0)\n"
  },
  {
    "path": "docs/user-guide/emails.md",
    "content": "---\nsearch:\n  boost: 3\n---\n\n# Guidelines on using emails\n\nEspoCRM is designed to be able to work with emails right from within the system without the necessity to use an email client separately. Though users may still opt to use an email client and have both sent and received emails synced to Espo.\n\nIn this article:\n\n* [IMAP accounts](#imap-accounts)\n* [SMTP accounts](#smtp-accounts)\n* [Working with emails](#working-with-emails)\n* [Sending emails](#sending-emails)\n* [Email folders](#email-folders)\n* [Group email folders](#group-email-folders)\n* [Email filters](#email-filters)\n* [Email templates](#email-templates)\n* [Manual import](#manual-import)\n* [See also](#see-also)\n\n## IMAP accounts\n\n*The section concerns email receiving.*\n\n!!! note\n\n    You need to have [cron](../administration/server-configuration.md#setting-up-crontab) properly configured in your system to have inbound emails working.\n\nA regular user can set up an IMAP account on the Personal Email Accounts page (Emails tab > top-right menu > Personal Email Accounts).\n\nSpecify what folders to monitor in *Monitored Folders* field. By default, it's set to INBOX. \n\nIf you use an **external email client** for email sending, you can add *Sent* folder to monitored ones. Emails sent from the external client will be imported to Espo. Note that your external client needs to be configured to store sent emails on the IMAP server.\n\n*Fetch Since* allows you to choose the date emails should be imported from. Set it to some date prior today if you need to archive old emails.\n\nThere is the ability to specify *Folder* in a Personal Email Account. Incoming emails will be put in that Email Folder folder. Note that Emails Folders are personal for users.\n\nFor regular users, access to Personal Email Accounts must be allowed in Roles.\n\n## SMTP accounts\n\n*The section concerns email sending.*\n\nUsers can set SMTP settings in their Personal Email Accounts. Personal Email Accounts are available under: Emails tab > top-right menu > Personal Email Accounts. \n\nFor regular users, access to Personal Email Accounts must be allowed in Roles.\n\nAn administrator can also allow to use the main system SMTP account as well as Group Email Accounts (needs to mark as Shared).\n\nUsers can have multiple SMTP accounts.\n\n!!! important\n\n    Email addresses that user can use to send emails from must be defined in *Emails* field of the *User* record. Only the admin can define user's email addresses (by default).\n\n## Working with emails\n\nEmails are fetched by Cron (in the background) every few minutes (period can specified by the administrator).\n\nA user can see emails on the page accessed through the *Emails* tab.\n\nThere are the following default folders available:\n\n* All – all emails in the system the user has access to; the user can see even emails of other users here (if Roles allow);\n* Inbox – incoming emails sent to the user are automatically placed here;\n* Sent – emails sent by the user;\n* Draft – emails composed by the user but not yet sent; \n* Archive – inbox emails that the user explicitly moved to the Archive;\n* Trash – inbox emails that the user explicitly moved to the Trash.\n\nAdditionally, there are also user's Email Folders and Group Email Folders listed.\n\nThe Email's *Status* field has the following values:\n\n* *Sent* – sent by means of the CRM;\n* *Imported* – fetched from an IMAP account or imported manually;\n* *Draft* – created as a draft and not yet sent.\n\nWhen a new email comes, the system tries to recognize which record this email belongs to. It can link it with Account, Lead, Opportunity, Case (and also Contact in B2C mode), etc. If it wasn't recognized, then the user can link it manually by filling in the *Parent* field.\n\nIf an email came from a new potential client, the user can convert it to a Lead (from the top-right menu).\n\nIt's possible to create a Task or Case from an email record (from the top-right menu).\n\nIf email addresses (From, To, CC) of the email record are known to the system, it will show the person they are related to (Contact, Lead, User, etc.). If some email address is new, you can create a Contact right from there.\n\nAll emails related to a specific record are shown in the History panel of that record. If some email is related, for example, to an opportunity but the opportunity is related to an account, it will be shown both in the opportunity and the account.\n\nWhen **removing** an email it gets removed from the system entirely, so that it will disappear from their *Inbox*. To prevent this, use *Move to Trash*. An administrator may not grant *delete* access for users to prevent losing emails.\n\nOn the list view it's possible to **drag & drop** emails into folders by dragging by a subject link (as of v7.3).\n\n### Inbox\n\nEmails related to a user through the *Users* relationship are referred as their Inbox emails. Only Inbox emails can be moved to Archive, Trash or a personal Email Folder by a user. Only Inbox emails can be marked as read, not read or important by a user.\n\n!!! important\n\n    The same Email record can be located in the Inbox of multiple users.\n\nAn administrator can view and manage users an email is related to by clicking *View Users* action from the dropdown next to the *Edit* button.\n\nAs of v8.5. Regular users can view users an email is related to: Email detail view > dropdown next to *Edit* > View Users. If a user has *edit* access to a particular Email, they can also add other users to the Email so that it will appear in the Inbox of those users. Adding users requires the assignment permission.\n\n### Concept\n\nEspo does not work exactly like a regular personal email client. Espo is a central place where emails from multiple email accounts are gathered.\n\nThe same email record can appear in the inboxes of multiple users, for example, when they were both recipients of the email. When the same email is imported from multiple email accounts, only one email record will be stored in Espo. Emails are recognized as duplicates by their *Message-ID*.\n\nA user with high privileges can see an email even if it was not addressed to them. This allows the monitoring of subordinates' communication within the organization.\n\nEmail folders in Espo are not connected with IMAP folders, there's no two-way sync between them by design.\n\n## Sending emails\n\nYou can compose a new email in a few ways:\n\n* using the *Compose Email* button on the Emails list view;\n* replying on another email;\n* clicking on an email address of some record;\n* using the *Compose Email* action from the Activities panel on the detail view of a particular record.\n\nThere is the ability to select a template for an email you compose.\n\nYou can set up the email signature in the Preferences. This signature will be used for all emails you compose.\n\nIt's possible to use an **external email client** – the default one on your computer or device. For this, check *Use an external email client* in the Preferences.\n\n### Scheduled send\n\nWhen composing an email, it's possible to schedule it to be sent at a specific time. The email is saved to Drafts. The scheduled time can be changed after save.\n\nThe scheduled send is available from the dropdown menu next to the Send button.\n\n## Email folders\n\nUsers can create their personal Email Folders to put some emails in for convenience. To create or edit folders, follow: the Emails list view > dropdown in the top-right corner > Folders. *Skip Notification* means that you won't be notified about incoming emails that get to the specific folder. By utilizing Email Filters, it's possible to put emails in folders automatically by specific criteria.\n\n!!! note\n\n    Email folders in EspoCRM have nothing to do with IMAP folders.\n\n## Group email folders\n\n*As of v7.3.*\n\nGroup Email Folders are shared for teams. An administrator can create group email folders and specify which teams have access to a particular folder.\n\nIf an email is moved from a group folder to a personal folder or the Inbox, it will unlink the email from that group folder.\n\nThere's the ability to automatically put inbound emails imported through a group email account to a specific group folder. It's also possible to move emails matching an email filter to a specific group folder (the filter should be related to a group email account).\n\nUsers that have access to a group folder can put there emails that they have edit access to. If an email is located in a group folder, a user does not have edit access to, they won't be able to move that email to another folder.\n\nThe field-level-security (in Roles) can be used to restrict the ability to change (edit) the group folder.\n\n## Email filters\n\nAn administrator can create global Email Filters to skip not desirable emails. They are available at Administration > Email Filters.\n\nRegular user can create Email Filters for their Personal Email Accounts or for their entire inbox. They are available at: Emails > dropdown in top-right corner > Filters.\n\nAvailable filter parameters:\n\n- From\n- To\n- Subject\n- Body Contains\n- Body Contains All\n\nIf any of specified filter parameters does not match for a particular email, then the filter is not applied.\n\nWildcard (*) can be used in filter parameters.\n\nAvailable actions:\n\n* Skip – email will be put in *Trash* or not imported if the filter is related to a Personal Email Account;\n* Put in Folder – imported emails will be put into a specified user's folder automatically.\n\nAdditional behavior parameters:\n\n- Mark as Read\n- Skip Notification\n\n\n## Email templates\n\nEmail Templates are available at: Emails > dropdown in top-right corner > Email Templates. They can be used both for Mass Email sending and for regular emails. *One-off* checkbox means that the email template is supposed to be used only once, what is usual for email marketing.\n\nIt's possible to use placeholders in an email template's body and subject, for example, {Account.name}, {Person.emailAddress}. They will be replaced with values of a Parent record.\n\nYou can use additional reserved placeholders in the template body: `{optOutUrl}` and `{optOutLink}`. Available additional placeholders are listed in a side panel when you compose an email template.\n\nAn example of an unsubscribe link for Mass Email:\n\n```\n<a href=\"{optOutUrl}\">Unsubscribe</a>\n```\n\nThe list of available additional placeholders:\n\n* `{today}` – today's date,\n* `{now}` – current date & time,\n* `{optOutUrl}` – opt-out url (only for mass email),\n* `{optOutLink}` – opt-out link (only for mass email),\n* `{optInUrl}` – opt-in url (only for lead capture confirm opt-in),\n* `{optInLink}` – opt-in link (only for lead capture confirm opt-in).\n\n### Handlebars support\n\nEmail Templates also support the Handlebars templating engine. It's the same template system used for [PDF templates](printing-to-pdf.md#templates) with double-brace placeholders, like `{{name}}`.\n\nThe Handlebars engine is only applied when an Email has a non-empty *Parent* field. The regular email template placeholder values are not available for Handlebars helpers.\n\n## Manual import\n\nIt's possible to manually import specific emails. For example, if a customer sent an email to an employee's private email address, it may be reasonable to log that email in the CRM manually.\n\nThe are two ways of importing emails:\n\n* Archive Email – create an email manually by specifying all fields on a form;\n* Import EML (as of v8.4).\n\nThe ability to import emails requires a user to have access to the Import scope (set in Roles).\n\n## See also\n\n* [Shortcut keys](https://docs.espocrm.com/user-guide/shortcuts/#emails)\n* [Email Templates quick tour](https://app.supademo.com/demo/cmoa0rxu403amv50jd7s9f97i)\n* [Email Sync quick tour](https://app.supademo.com/demo/cmp44ha8q00470jwspqw0gqol)\n* [Email Sending quick tour](https://app.supademo.com/demo/cmon02qj201x3y30j8x2jar8b)\n"
  },
  {
    "path": "docs/user-guide/export.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Export\n\nThe Export feature allows you to extract record data in XLSX (Spreadsheet) and CSV formats.\n\n* [How to export](#how-to-export)\n* [Access control](#access-control)\n* [Parameters](#parameters)\n* [CSV delimiter](#csv-delimiter)\n* [See also](#see-also)\n\n## How to export\n\n### Step 1\n\nOn the list view make a search with needed filters and then click *Select All Results* (from the dropdown, see the screenshot below).\n\n![Select all results](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/export/export-1.png)\n\n### Step 2\n\nClick the *Actions* dropdown, then click *Export*.\n\n![Click Export action](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/export/export-2.png)\n\n### Step 3\n\nThe modal window will show up where you can specify export parameters.\n\n![Click Export action](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/export/export-3.png)\n\nYou can select specific fields to be exported or check to export all available fields.\n\n### Step 4\n\nAfter clicking the Export button the export, two scenarios are possible.\n\n* Export will be processed right away and you will receive a prompt to download the file.\n* Export will be processed in idle (if the number of exported records exceeds the specific threshold). A modal dialog will be shown. After the process is finished, you will be able to download the file.\n\n## Access control\n\nAn administrator can disable export function for all non-admin users under Administration > Settings > Disable Export.\n\nAlso it's possible to control access to export function via Roles with the *Export Permission* parameter.\n\n## Parameters\n\n### Lite mode\n\nThe *Lite* mode consumes much less memory. Recommended if a big number of records is exported.\n\n## CSV delimiter\n\nUsers can specify the delimiter for CSV export in their Preferences.\n\nThe default delimiter for the system can be changed manually in `data/config.php`, parameter `exportDelimiter`.\n\n## See also\n\n* [Export feature quick tour](https://app.supademo.com/demo/cmk5pysph1o5ok6skq80atm08)\n* [Export Import extension](../extensions/export-import/overview.md)\n* [Import and export tool for quick data migration](https://www.espocrm.com/tips/import-export/)\n"
  },
  {
    "path": "docs/user-guide/imap-smtp-configuration.md",
    "content": "﻿# IMAP and SMTP configuration\n\nIn this article:\n\n* [IMAP configuration](#imap-configuration)\n* [SMTP configuration](#smtp-configuration)\n* [Google Workspace](#google-workspace)\n* [Gmail](#gmail)\n* [Outlook](#outlook)\n* [Yahoo](#yahoo)\n\n## IMAP configuration\n\n!!! note\n\n    You need to have cron properly configured in your system to have inbound emails working.\n\nIMAP allows you to retrieve your emails from a mail server. To set up an IMAP account, do the following steps:\n\n1. Go to Emails Tab > top-right menu > Personal Email Accounts.\n2. Click on *Create Personal Email Account*.\n3. In the *Main* section, specify your Email Address. The *Name* of the personal email account is generated automatically, but you can change it. *Fetch since* allows you to choose a date from which emails will be imported. If you want to archive old emails, set it to some past date.\n\n![Create personal email account](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/imap-smtp-configuration/1.png)\n\n4. In the *IMAP* section, enter your *Host* name, your *Username* and *Password*. Tick off *SSL* for a secure connection. The IMAP *Port* will be generated automatically.\n\n![IMAP configuration](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/imap-smtp-configuration/2.png)\n\n5. Specify what folders to monitor in the *Monitored Folders* field. By default, it is set to INBOX. If you use some external email client to send emails, you can add the Sent folder to archive those emails.\n6. *Put in Folder* field allows you to specify an Espo email folder in which incoming emails will be put.\n7. Click on *Test Connection* to check whether everything was set correctly. If the connection is successful, click *Save*.\n\n## SMTP configuration\n\nSMTP is for sending emails. Users can setup SMTP settings their Personal Email Accounts. An administrator can also allow to use the System SMTP (by marking it shared).\n\nUsers can have multiple SMTP accounts. However, email addresses a user can use to send emails from are defined by email addresses of the User record (Administration > Users).\n\nTo set up an SMTP account, do the following:\n\n1. Navigate to the *Personal Email Accounts* page: Emails Tab > top-right menu > Personal Email Accounts.\n2. Tick off the *Use SMTP* box.\n3. Enter your *SMTP Host* name, in the SMTP security field select *STARTTLS* or *SSL/TLS* for a secure connection. The proper *SMTP Port* will be set automatically.\n4. Tick off the *SMTP Auth* box and enter your *Username* and *Password*.\n5. Click on the *Send Test Email* button to send a test email to a specified email address.\n6. Save.\n\n![SMTP configuration](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/imap-smtp-configuration/3.png)\n\n## Google Workspace\n\n1. Sign into your *Google Admin console*.\n2. Navigate to *App > G Suite > Gmail > Advanced settings*.\n3. Select the organizational unit in the *organizations section*.\n4. Under the POP and IMAP Access, uncheck the *Disable POP and IMAP access for all users box* checkbox.\n5. Each user has to enable IMAP access as described for [Gmail Account](#gmail).\n\n## Gmail\n\n1. Sign into your *Gmail Account*.\n2. Select ![Settings](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/imap-smtp-configuration/4.png) > Settings.\n3. Click the *Forwarding and POP/IMAP* tab.\n4. In the *IMAP access*, select *Enable IMAP*.\n5. Click on *Save Changes*.\n\n!!! note\n\n    There are two ways in which you can set up IMAP and SMTP for Gmail account:\n\n    * Use the [Google Integration](https://www.espocrm.com/extensions/google-integration/) extension that provides a secure authentication via Oauth2.\n    * Use a generated [App Password](https://support.google.com/accounts/answer/185833). Requires enabling 2-step verification for your Google account.\n\nFor more information, follow the [link](https://support.google.com/mail/answer/7126229?hl=en).\n\n## Outlook\n\nTo be able to connect to Outlook.com or Microsoft 365 email accounts, you need to install the [Outlook Integration](https://www.espocrm.com/extensions/outlook-integration/) extension.\n\n1. Go to your *Outlook Account*.\n2. Open Settings ![Settings](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/imap-smtp-configuration/4.png).\n3. On the navigation panel, select *Mail > Forwarding and IMAP*.\n4. *Sign in* if required.\n5. Check *Let devices and apps use IMAP*. Here you can also view your IMAP and SMTP settings.\n6. Click *Save* button.\n\n!!! important\n\n    If the STARTTLS encryption method does not work for IMAP, try the SSL/TLS method.\n\n## Yahoo\n\nConfiguration details are available [here](https://help.yahoo.com/kb/SLN4075.html).\n\n## See also\n\nSee the articles for specific providers:\n\n* [Gmail](https://support.google.com/accounts/answer/185833)\n* [Yahoo](https://in.help.yahoo.com/kb/SLN15241.html)\n* [Outlook](https://support.microsoft.com/en-us/account-billing/using-app-passwords-with-apps-that-don-t-support-two-step-verification-5896ed9b-4263-e681-128a-a6f2979a7944)\n"
  },
  {
    "path": "docs/user-guide/invoices.md",
    "content": "# Invoices\n\nThe Invoices feature is available in [Sales Pack](https://www.espocrm.com/extensions/sales-pack/) extension.\n\nAn Invoice is a billing document issued to a customer that details the products or services provided, including their quantities, prices, applicable taxes, and the total amount due.\n\nYou can add the *Invoices* panel to the Account detail view to be able to see related sales orders. Administration > Layout Manager > Accounts > Bottom Panels.\n\nYou can add the Invoices panel to Opportunity detail view at Administration > Layout Manager > Opportunities > Bottom Panels.\n\nIn the article:\n\n* [Converting from Opportunity, Quote or Sales Order](#converting-from-opportunity-quote-or-sales-order)\n* [Total values layout](#total-values-layout)\n* [Invoice items](#invoice-items)\n* [Allocations](#allocations)\n* [Payment terms](#payment-terms)\n* [Debit notes](#debit-notes)\n* [Rounding](#rounding)\n* [Printing to PDF](#printing-to-pdf)\n* [Sending in email](#sending-in-email)\n* [Automatic numbering](#automatic-numbering)\n* [Copying values from product to invoice item](#copying-values-from-product-to-invoice-item)\n* [Automation with Workflows or BPM](#automation-with-workflows-or-bpm)\n* [Locking](#locking)\n* [Fields](#fields)\n* [E-Invoicing](#e-invoicing)\n\n## Converting from Opportunity, Quote or Sales Order\n\nMethod 1. Create a new Invoice, on the form, specify the needed opportunity/quote/sales order. Data will be copied from the opportunity/quote/sales order to the created invoice.\n\nMethod 2. Create a new Invoice from Invoices relationship panel on the detail view of the opportunity/quote/sales order.\n\n## Total values layout\n\nThe layout of total value fields (in the bottom on detail view) can be modified at Administration > Layout Manager > Invoices > Bottom Total.\n\n## Invoice items\n\nAn Invoice has the list of items. Each item can represent a certain product or a service with the description, quantity, tax rate, list price, and unit price fields. It's possible to sort items manually.\n\nThere is the ability to add custom fields for Invoice Item entity type using the Entity Manager.\n\n### Invoice Items layout\n\nThe layout of Invoice Items can be modified at Administration > Layout Manager > Invoice Items > List (Item).\n\n### List prices\n\nList prices for invoices are disabled by default. You can enable them at Administration > Sales Pack Settinfs > List Prices in Invoices, then add the *List Price* field to the Invoice Items layout.\n\n### Discount rate\n\nIt's possible to specify a discount in percents. To have this ability, an administrator should add the *Discount (%)* field to the *List (Item)* layout.\n\n## Allocations\n\nInbound payments, credit notes, and write-offs can be allocated to an invoice. Allocations reduce the amount due of an invoice.\n\nApplied allocations can be viewed in the Allocations panel of an invoice. To view details of a specific allocation, click View from the dropdown.\n\n## Payment terms\n\n*As of Sales Pack v4.0.*\n\nPayment term profiles can be managed at Administration > Payment Terms Profiles. The default payment term profile can be set at Administration > Sales Pack Settings. This profile will be pre-filled upon invoice creation.\n\nA payment term profile defines items that correspond to payment installments. Each item defines a portion in percents and the number of days. Portions of all items must add up to 100. The number of days is used to calculate the Date Due of the installment by adding the value to the Date Invoiced.\n\n!!! example \"Examples\"\n\n    - Net 30. Use one item with 100% portion and 30 days.\n    - CIA 25 / Net 20. 25% immediately and the rest after 20 days. Use two items: 25% with 0 days and 75% with 25 days.\n\nPayment installments of a created invoice are available in the Installments panel in the Invoice detail view. The status of each installment updates automatically when a payment is allocated to the invoice. It can be one of the following: Unsettled, Partially Settled, or Settled.\n\nA payment term profile can be assigned for a specific Account. The assigned to an account profile will be used when an invoice is created for that account. Note that the Payment Term Profile field is not added to the Account detail view by default. You need to add it at Administration > Entity Manager > Account > Layouts > Detail.\n\n## Debit notes\n\n*As of Sales Pack v4.0.*\n\nAn invoice can be issued as a debit note. In the system, a debit note is an invoice record with the Type field set to *Debit Note*.\n\nA debit note can be created at: Invoices tab > top right menu > Create Debit Note.\n\nBy default, debit notes use separate numbering. To use the same numbering, check *Do not use separate numbering for Debit Notes* at Administration > Sales Pack Settings.\n\nTo configure the debit note number prefix or change the next number, go to Administration > Entity Manager > Invoice > Fields > Number for Debit Notes (auto-incremented).\n\nIn a PDF Template, use `{{type}}` placeholder to print the type of the invoice document: Invoice or Debit Note.\n\n## Rounding\n\n*As of Sales Pack v4.0.*\n\nA rounding can be applied to an invoice. The invoice rounding is mandatory in some countries.\n\nThe rounding is applied before the grand total. The rounding method is controlled by a Rounding Profile assigned to the invoice.\n\nRounding profiles can be managed at Administration > Rounding Profiles. A rounding profile defines a rounding factor.\n\nRounding factor examples:\n\n- 1 – round to a whole number\n- 0.5 – round to 50 cents\n- 0.01 – round to 1 cent\n\nThe default rounding profile can be set at Administration > Sales Pack Settings. This profile will be pre-filled upon invoice creation.\n\nWhen a credit note is created for an invoice, it inherits the rounding profile from the invoice.\n\nIn some cases, when tax-inclusive pricing is used, the discrepancy between the expected amount and the sum of the computed net prices is recorded on the rounding amount line.\n\n## Printing to PDF\n\nInvoices can be printed to PDF. This action is available in the dropdown next to Edit button on the Invoice detail view. Then, you will be prompted to select a template. More info about printing to PDF is available [here](printing-to-pdf.md).\n\n### Templates\n\nSee the documentation [for quote templates](quotes.md#templates).\n\n### Tax number\n\nThe Sales Pack adds the *Tax Number* field to the Account entity type. Use this field to store VAT numbers. Note that including the VAT number on the invoice is mandatory in many jurisdictions.\n\n## Sending in email\n\nAn Invoice PDF can be sent in an email as an attachment. Open an invoice record, click the dropdown next to Edit button and then click Email PDF.\n\nThe default email template can be set by the administrator: Administration > Sales Pack Settings > Email Templates.\n\nTo have the Invoice entity selected as the email's parent, the administrator should add the Invoice entity type to the parent type list. Administration > Entity Manager > Email > Fields > Parent > Entity List. As of v3.0.\n\n## Automatic numbering\n\nBy default, the *Number* field is auto-incremented. You can disable auto-increment at Administration > Entity Manager > Invoice > Fields > Number. It's also possible to make the number field read-only.\n\nThe prefix of the next number, the next number itself and the quantity of digits in the number can be configured at Administration > Entity Manager > Invoice > Fields > numberA.\n\nDraft invoices use a separate numbering. When an invoice is issued, it receives its final number. You can disable or enabled this feature at Administration > Sales Pack Settings > Use separate numbering for drafts.\n\nBy default, there is no *Name* field on the *Detail* layout. The *Number* is used as a name. You can add the Number field at Administration > Entity Manager > Invoice > Layouts > Detail.\n\nBy default, the *Name* field is synced with *Number*. To be able to specify arbitrary names, you need to disable the *Sync with Number* and *Read-only* parameters at Administration > Entity Manager > Invoice > Fields > Name.\n\n\n## Copying values from product to invoice item\n\nField values can be transferred from a product to an invoice item upon product selection. Field names you want to be copied should coincide in Product and Invoice Item entities.\n\nYou can select which fields you need to be copied at Administration > Entity Manager > Invoice Item > Fields > Product > Fields to Copy.\n\n## Automation with Workflows or BPM\n\nThe following service actions are available in the Workflows and BPM tools:\n\n* Add Invoice Items\n* Convert Currency\n* Send in Email\n\n## Fields\n\nAdditional fields available in the Invoice entity type:\n\n* Buyer Reference\n* Purchase Order Reference (not available in the Detail layout by default, can be added in the Layout Manager)\n* Note – A note exposed to the customer. Unlike the Description field which is for internal use.\n\n## E-Invoicing\n\n*As of Sales Pack v2.4.*\n\nInvoices can be exported to EN 16931 electronic invoices in a UBL format. The following CIUS specifications are supported:\n\n* XRechnung\n* PEPPOL BIS Billing 3.0\n* CIUS-RO e-Factura\n* CIUS-IT\n* CIUS-AT-GOV\n* CIUS-AT-NAT\n* CIUS-ES-FACE\n* NLCIUS\n\nTo export an Invoice to a UBL file, click **E-Invoice** from the dropdown menu next to the **Edit** button on the Invoice detail view. The UBL file can be also attached along with a PDF when sending an Invoice in email.\n\n!!! note\n\n    An E-Invoice can exported only if it is valid. It must include certain mandatory fields depending on the specification.\n\n### Settings\n\nE-Invoicing settings are available at Administration > Sales Pack Settings > Electronic Invoicing. Here you can specify the system **Default Format** to prevent the need to select the format each time you are exporting an invoice.\n\nSpecify **Seller Information** fields that will be included in electronic invoices. Fields, such as Company Name, Company Address, Electronic Address, VAT Number, etc.\n\n### Account\n\nThe Sales Pack adds additional fields to the Account entity type. The following fields of the Account are included in the E-Invoice:\n\n* Tax Number – to store VAT number;\n* Electronic Address Scheme\n* Electronic Address Identifier\n\nAdd these fields to the Account's *Detail* layout under: Administration > Entity Manager > Account > Layouts > Detail.\n\n### Invoice\n\nA standard you use may require the Buyer Reference, Purchase Order Reference. The corresponding fields exist in the Invoice entity type, an administrator can add them to the Detail layout.\n\nAdditional fields that are mapped to E-Invoice:\n\n* Buyer Reference\n* Purchase Order Reference\n* Note\n\nIf you have a requirement to add fields that are not present in Espo out-of-the-box, a developer can implement a custom e-invoice preparator to map custom fields to e-invoice.\n\n### Country codes\n\nThe EN 16931 standard requires countries to be represented as ISO 3166-1 alpha-2 codes. But in Espo, the *Address* field allows a country to be an arbitrary string. As of EspoCRM v8.3 it's possible to [map](../administration/addresses.md) country names to ISO 3166-1 alpha-2 codes. This mapping is used when E-Invoices are generated.\n\nNote that it's possible to automatically populate country records with English names.\n\nExample: If you run business from Germany, your customer is also in Germany and you use the word *Germany* when storing the country in Espo, you need to create the *Germany* Address Country record with the *DE* code.\n\n### EN 16931 tax mapping\n\nTax codes can be mapped to [UNCL5305](https://docs.peppol.eu/poacc/billing/3.0/codelist/UNCL5305/) category code.\nAdditionally, a mapping entry can specify a tax class. If the tax class is specified, the mapping will be applied\nto a document items with a product associated with that tax class.\n\nAccess mapping at: Administration > EN 16931 Tax Mapping.\n\n## Locking\n\nAn Invoice can be locked if it's completed or canceled. When a record is locked, a specific fields become read-only. An administrator can configure the field list at: Administration > Entity Manager > Invoice > Edit.\n\nIf the settings parameter *Forbid order unlocking* is checked, once a record is locked, it can be unlocked only by an administrator.\n\n## See also\n\n* [Custom calculations for Quote totals](../development/quote-custom-calculations.md)\n"
  },
  {
    "path": "docs/user-guide/knowledge-base.md",
    "content": "# Knowledge Base\n\nThe Knowledge Base provides the ability to create articles. Articles may contain information about your products, guidelines for clients, or help for internal users to improve their productivity.\n\nTo make an article available in the Portal, you need to set its status to *Published* and select the needed portal in the *Portals* field. Make sure that the Portal Role allows access to the Knowledge Base scope and the navigation menu tab is added in the Portal.\n\nIf you specify the *Expiration Date*, then the article will be automatically hidden from the Portal on that date.\n\nAn order in which articles are listed can be manipulated by actions in the dropdown menu of a specific article.\n\nKnowledge Base articles can be associated with Case records. This provides quick access to information from a Case record.\n\n## Categories\n\nCategories allow to group articles. One category can contain multiple sub-categories. Each article can be related to one or multiple categories.\n\nThe Knowledge Base Category is a separate entity type, hence access can be controlled by Roles.\n"
  },
  {
    "path": "docs/user-guide/mail-merge.md",
    "content": "# Mail Merge (mass snail mailing)\n\nThe Mail Merge feature provides the ability to mass generate snail mails for printing.\n\n1\\. You need to have a Target List populated with recipients. You can access Target Lists by navigating to the Campaigns tab and clicking the Target Lists button in the top-right corner.\n\n2\\. Create a PDF Template for an entity type you want to send mails to. If the Target List contains records of different entity types (e.g. both Contacts and Leads) you need to create separate templates for each one.\n\n!!! note\n\n    An Administrator can create a template at Administration > PDF Templates. The Templates tab is hidden by default, but can be added by the administrator at Administration > User Interface.\n\n3\\. Create a campaign of the *Mail* type. Specify the Target List for this Campaign. Specify the templates you created before.\n\n4\\. On the Campaign detail view, click the dropdown next to the *Edit* button and then click *Generate Mail Merge PDF*. Select an entity type and click *Proceed* button.\n\nIt will generate a single PDF document (or multiple PDFs zipped, depending on the used engine) for multiple records that you can print.\n\n!!! note\n\n    By default, records with empty *Address* field are skipped.\n\n!!! warning\n\n    If a user have access to the Campaign record (for example, a manager assigned the campaign to an employee), they will be able to mass print targets even ones they don't have access to.\n"
  },
  {
    "path": "docs/user-guide/markdown.md",
    "content": "# Markdown syntax\n\nText fields support Markdown syntax.\n\n## Code\n```\n`some text`\n```\n\n`some text`\n\n## Multiline code\n\n```\n``` some text ``` \n```\n\n```\nsome text\n```\n\n## Strong text\n\n```\n**some text**\n```\n\n**some text**\n\n## Emphasized text\n\n```\n*some text*\n```\n\n*some text*\n\n## Deleted text\n\n```\n~~some text~~\n```\n\n~~some text~~\n\n## Blockquote\n\n```\n> some\n> test\n```\n\n> some\n> text\n\n## Link\n\n```\n[link text](https://www.espocrm.com)\n```\n[link text](https://www.espocrm.com)\n\n## Numbered list\n\n```\n1. Some item\n2. Another item\n```\n\n1. Some item\n2. Another item\n\n## Unnumbered list\n\n```\n* Some item\n* Another item\n```\n\n* Some item\n* Another item\n\n## Horizontal line\n\n```\n___\n```\n\n## Image\n\n```\n![Alt text](https://domain/file.png)\n```\n\nUsing an uploaded attachment:\n\n```\n![Alt text](?entryPoint=image&id=00000000)\n```\n\n### Table\n\n```\n| Month    | Amount   |\n| -------- | -------- |\n| January  | $200     |\n| February | $100     |\n```\n\nAlignment:\n\n```\n| Left     | Center   | Right    |\n| -------- | :------: | -------: |\n| January  | Good     | $200     | \n| February | Normal   | $100     |\n```\n\n### Checklist\n\n```\n- [x] Item 1\n- [ ] Item 2\n```\n"
  },
  {
    "path": "docs/user-guide/mass-email.md",
    "content": "# Mass Email\n\nIn this article:\n\n* [Email accounts](#email-accounts)\n* [How to send mass email](#how-to-send-mass-email)\n* [Test sending](#test-sending)\n* [Opt-out](#opt-out)\n* [Tracking URL](#tracking-url)\n* [Target lists](#target-lists)\n* [Campaign log](#campaign-log)\n* [Bounce emails](#bounce-emails)\n* [Informational emails](#informational-emails)\n* [Settings](#settings)\n* [Troubleshooting](#troubleshooting)\n* [See also](#see-also)\n\n\n## Email accounts\n\nThe system email account (the group email account designated as system at Administration > Outbound Emails) is used for mass emails by default. Group email accounts with *Is for Mass Email* checked can also be used. An email account can be selected when creating a Mass Email record.\n\n## How to send mass email\n\nYou need to have at least one **Target List** with target records and an **Email Template** in your CRM.\n\n1. Create a new Campaign of type *Email* or *Newsletter*. Select one or a few target lists in the Target Lists field.\n2. After the Campaign record is created, create a Mass Email for this campaign: from the Campaign detail view, click the plus icon in the Mass Email panel. Specify the Date Start (when emails should be sent) and select an email template. Make sure the Status is set to *Pending*.\n\nIf everything is set up right, emails should go out. They will be sent in portions. You can change the portion size at Administration > Outbound Emails. The administrator can change the **scheduling** at Administration > Scheduled Jobs > Send Mass Emails.\n\nYou can check if emails are sent in the Log panel on the Campaign detail view.\n\n## Test sending\n\nClick the right-side dropdown in a needed record in the Mass Email panel and then click *Send Test*.\n\n## Opt-out\n\nThe system will append an opt-out link to all sent emails in case it's missing in the email template body. You can use a custom opt-out link in your email template.\n\n!!! example\n\n    ```html\n    <a href=\"{optOutUrl}\">Unsubscribe from the mailing list.</a>\n    ```\n\nAn administrator can disable the mandatory opt-out links at Administration > Outbound Emails.\n\nIf *Opt-Out Entirely* is checked for a Mass Email, once the recipient clicks on the opt-out link, their email address will be marked as opted out so that marketing emails will never be sent to them, unless the email address is unmarked back. If the parameter is not checked, then the recipient will be marked as opted-out in all Target Lists related to the current Campaign. They still can receive marketing emails when a different Target List is used in another Campaign.\n\n## Tracking URL\n\nIf you want to know that your recipient opened the link from your email, you need to create a **Tracking URL**. Specify a **Name**\n and a **URL** where your link should lead to. Then, you need to paste a generated code into your email template.\n\n!!! example\n\n    ```html\n    <a href=\"{trackingUrl:55f2c87b09a220a78}\">Try our demo</a>\n    ```\n\n## Target lists\n\nTarget Lists contain lists of Accounts, Contacts, Leads and Users records. Custom entities of the Person and Company types are supported too.\n\nUsers can populate target lists manually using the *Select* action in the corresponding panel on the Target List detail view. There is the ability to make filtering and then *Select All Results* of the search.\n\n### Populating target lists with Reports\n\nThe [Reports](reports.md#syncing-with-target-lists) tool provides the ability to populate target lists with records matching specific criteria.\n\n### Excluding target lists\n\nSpecify *Excluding Target Lists* to avoid sending mass emails to certain recipients. If there is a record with an email address that matches the email address of an excluded record, it will be excluded as well.\n\n### Custom entity support\n\n*[As of v7.1.](https://github.com/espocrm/espocrm/issues/2203)*\n\nAn administrator needs to create a many-to-many relationship between the Target List and the custom entity (of Person or Company type). Then, add the panel to the *Bottom Panels* layout of the Target List entity type.\n\n## Campaign log\n\nIn the Campaign Log, you can see emails that have been sent, opened emails, bounced emails, who opted out, and who clicked the link in the email.\n\n* Sent email\n* Links clicked by the recipient\n* Recipients who opted out\n* Bounced emails (not delivered to the recipient)\n* Emails opened by the recipient (disabled by default)\n\nIt's possible create a new Target List (dropdown in the top-right corner on panel) based on records from the log. For example, you can pick only contacts that clicked on a link (tracking URL).\n\n## Bounce emails\n\nA bounce email is an automatic email message from an email system reporting that a sent message has not been delivered.\n\nThere are two types of bounced emails: hard and soft. The hard-bounce will mark the recipient email address as invalid so no more emails will be sent to it in future. Soft-bounces will be only logged in the campaign log.\n\nBounced emails can be handled only by a *Group Email Account*. \n\n## Informational emails\n\n*As of v9.1.*\n\nInformational emails are not related to marketing. For example, they may provide details about a license update or a notice about scheduled service maintenance.\n\nFor sending informational emails, choose the *Informational Email* type when creating a new Campaign.\n\nHow it differs from the regular Email type:\n\n* Mass emails are sent to all targets regardless of their opt-out status.\n* Opt-out link is not included.\n* Tracking URLs do not function.\n* Open tracking does not function.\n\n## Settings\n\nOnly for the administrator.\n\nMass Email system parameters are available at Administration > Outbound Emails > Mass Email panel.\n\n* Max number of emails sent per hour – to avoid sending rate exceeding; the actual number of emails sent per hour will be always less than this limit; the more often the job is run per hour, the more close to the limit number the number of sent emails will be;\n* Max number of emails sent per batch – how many emails to send per job run per one Mass Email (as of v8.1);\n* Disable mandatory opt-out link − by default opt-out link is added even if it's absent in an Email Template, you can disable this behaviour;\n* Email Open Tracking − whether to track email opening (currently, not working reliably with most email providers);\n* Use [VERP](https://en.wikipedia.org/wiki/Variable_envelope_return_path) − for more reliable bounced email precessing.\n\nConfigure how often the sending job is run at: Administration > Scheduled Jobs > Send Mass Emails > Scheduling.\n\n## Troubleshooting\n\nOnly for the administrator.\n\n#### What to do if emails are not sent out\n\n1. Check if _Send Test_ works. If doesn't work, then check if system SMTP settings are correct.\n2. Check if you have setup cron for your system.\n3. Check if you have *Send Mass Emails* Scheduled Job and it is *Active* (Administration > Scheduled Jobs > Send Mass Emails). Check if there is something in the log.\n\n#### What if Tracking URLs have wrong URL that does not lead to your CRM\n\nCheck the *Site URL* parameter at Administration > Settings. The value must be the URL of your EspoCRM instance. This URL must be also accessible externally.\n\n#### Bounced emails are not being logged\n\nBounced emails can be handled by a Group Email Account only. Make sure that you have a Group Email Account that monitors the mailbox bounced emails are being sent to.\n\nAlso some mail server providers can deviate from standards, so bounced emails can be not distinguished.\n\nEnable *VERP* at Administration > Outbound Emails > Mass Email. This improves bounce recognition significantly. Note that it will work only if your SMTP provider supports VERP. \n\n## See also\n\n* [Mass Email tutorial](https://app.supademo.com/demo/cmnre9orw04ewyt0jo7p4lhfu)\n* [Campaigns quick tour](https://app.supademo.com/demo/cmnim3kjr01wvwn0j4g5jug04)\n* [Custom unsubscribe page](../development/campaign-unsubscribe-template.md)\n* [Drip Email Campaign with BPM](../administration/bpm-drip-email-campaign.md)\n"
  },
  {
    "path": "docs/user-guide/optimistic-concurrency-control.md",
    "content": "# Optimistic Concurrency Control\n\n*As of v7.0.*\n\nOptimistic Concurrency Control prevents data from being overwritten by other users between the time it is fetched and saved.\n\nIf a user tries to save a record that has already been modified by another user, a modal dialog will appear, prompting to resolve the conflict. For each changed field, it's possible to choose from the following values:\n\n* Current – the value the user attempted to write;\n* Actual – the value currently stored in the database;\n* Original – the value retrieved before modification.\n\nThe conflict won't occur if users modify different fields.\n\nAn administrator can enable the Optimistic Concurrency Control for an entity type under Administration > Entity Manager > {Entity Type} > Edit > Optimistic Concurrency Control.\n\nBy default, it's enabled for:\n\n* Knowledge Base\n* Email Templates\n* PDF Templates\n"
  },
  {
    "path": "docs/user-guide/printing-to-pdf.md",
    "content": "---\nsearch:\n  boost: 2\ntags:\n  - pdf\n---\n\n# Printing to PDF\n\nThe Print to PDF feature allows you to generate PDF documents with record data. The document content is defined by a Template.\n\n!!! warning \"Important\"\n\n    You need to have at least one Template for the entity type of the record you want to print.\n\nIn this article:\n\n* [Overview](#overview)\n* [Templates](#templates)\n\nSee also:\n\n* [Quick tour](https://app.supademo.com/demo/cmejvg02x0ly25gz3si01kay7)\n* [International fonts](https://github.com/espocrm/ext-pdf-fonts) (as of v10.0)\n\n## Overview\n\n### Printing single record\n\nThe *Print to PDF* action is available on the detail view under the dropdown next to the *Edit* button.\n\n### Printing multiple records\n\n*Print to PDF* is available in the list view as a mass action. You need to select needed records and click *Print to PDF* from the *Actions* menu. It will generate a single merged PDF file or multiple PDFs zipped (depending on a used engine) for multiple records.\n\nBy default, the maximum number of records is limited to 50. The limit is defined by the config parameter `massPrintPdfMaxCount`.\n\n### Access control\n\nAccess to PDF printing is controlled by Roles. An administrator can set a *read* access level for the *Template* entity type.\n\n### Engines\n\nPDF documents are generated from HTML code by the use a PDF engine. Out of the box, Espo supports [Dompdf](https://github.com/dompdf/dompdf) engine. [Tcpdf](https://github.com/tecnickcom/TCPDF) engine is available as an [extension](https://github.com/yurikuzn/ext-tcpdf/releases). Dompdf has better CSS support. Tcpdf supports some languages which Dompdf does not.\n\nThe engine can be switched at Administration > Settings > PDF Engine.\n\n## Templates\n\nTable of content: \n\n* [Code view](#code-view)\n* [Charset issues](#charset-issues)\n* [Access to templates](#access-to-templates)\n* [Page numbering](#page-numbering)\n* [Page breaking](#page-breaking)\n* [Condition checking](#condition-checking)\n* [Each iterator](#each-iterator)\n* [Lookup](#lookup)\n* [Expressions](#expressions)\n* [Logical expressions](#logical-expressions)\n* [Images](#images)\n* [Date & time formatting](#date-time-formatting)\n* [Number formatting](#number-formatting)\n* [Currency symbol](#currency-symbol)\n* [Text field](#text-field)\n* [Related records](#related-records)\n* [Multi-enum & Array fields](#multi-enum-array-fields)\n* [Checklist field](#multi-enum-array-fields)\n* [Barcode field](#barcode-field)\n* [Raw values](#raw-values)\n* [Maps](#maps)\n* [Custom helpers](#custom-helpers)\n\nAvailable under Administration > PDF Templates.\n\nFor more precise editing it's recommended to use Code View mode. To switch to Code View click on the button *</\\>*.\n\nYou can print fields of the record as well as fields of related records by utilizing placeholders (Handlebars like) in your template.\n\n!!! example \"Examples\"\n\n    * `{{name}}` – Name of the record;\n    * `{{assignedUserName}}` – Assigned User;\n    * `{{account.name}}` – Name of the related account.\n\n!!! note\n\n    If an attribute name coincides with a name of some helper, you can use the following form: `{{this.attributeName}}`.\n\nYou can specify a document title in the *Title* field (as of v7.0). `{$name}` placeholder is available to substitute an entity name.\n\n### Code view\n\nA code view mode can be enabled by clicking *</\\>* button. It allows you to edit raw HTML and make sure the layout is not messed up.\n\nWhen editing a template in the code view and using template helpers, you need to keep the HTML code valid. Otherwise, the markup will break. Follow the guidelines:\n\n1. Do not mix helpers with table tags such as TR, TD. Use the special *iterate* attribute instead.\n2. Avoid helpers inside tags. Bad: `<div {{#if true}} class=\"test\" {{/if}}>`. Good: `<div class=\" {{#if true}} test {{/if}} \">`.\n\n### Charset issues\n\nIf some characters are not displayed in generated PDF files, it can be usually solved by changing the font in the template. For the Arabic language, use 'AlArabiya' font, for Chinese, use 'CID-0 cs'.\n\n\n### Access to templates\n\nAn administrator can add the *Templates* tab under Administration > User Interface. Access to templates must be defined in Roles (the *Templates* scope).\n\n### Page numbering\n\nPlaceholders are only available in footer (and also header if the header is set to be printed on each page).\n\n* `{pageNumber}` – the current number of the page\n\n### Page breaking\n\nIn places where you need to have an explicit page break, add:\n\n```\n{{pagebreak}}\n```\n\n### Condition checking\n\n#### Conditional rendering attribute x-if\n\n*As of v8.4.*\n\n```\n<table>\n    <tr x-if=\"{{equal status 'Active'}}\">\n        <td></td>\n    </tr>\n    <tr x-if=\"{{or (equal status 'Active') (equal status 'Pending')}}\">\n        <td></td>\n    </tr>\n</table>\n```\n\nHelpers:\n\n* if\n* unless\n* ifEqual\n* ifNotEqual\n* equal\n* notEqual\n\n#### if\n\n```\n{{#if value}}\n    {{value}}\n{{/if}}\n```\n```\n{{#if value}}\n    {{value}}\n{{else}}\n    No value\n{{/if}}\n```\n\n```\n{{#if condition1}}\n    \n{{else if condition2}}\n\n{{else}}\n\n{{/if}}\n```\n\n#### unless\n\nOpposite to *if*.\n\n```\n{{#unless value}}\n    No value\n{{/unless}}\n```\n\n```\n{{#unless value}}\n    No value\n{{else}}\n    {{value}}\n{{/unless}\n```\n\n#### ifEqual\n\n```\n{{#ifEqual a b}}\n    a is equal b\n{{else}}\n    a is not equal b\n{{/ifEqual}}\n```\n\n#### ifNotEqual\n\nOpposite to *ifEqual*.\n\n#### equal\n\n*As of v8.4.*\n\nReturns boolean.\n\n```\n{{#if (equal status 'Active')}}\n    ...\n{{/if}}\n```\n\n#### notEqual\n\n*As of v8.4.*\n\nReturns boolean.\n\n```\n{{#if (notEqual status 'Active')}}\n    ...\n{{/if}}\n```\n\n### Each iterator\n\nLooping through a list of items.\n\nExample:\n\n```\n{{#each contacts}}\n    Contact name: {{name}}\n{{/each}}\n```\n\nArray (list):\n\n```\n{{#each array}}\n   {{this}} – item\n   {{@index}} – index\n{{/each}}\n```\n\nObject (map):\n\n```\n{{#each map}}\n   {{this}} – item\n   {{@key}} – key\n{{/each}}\n```\n\n!!! important\n\n    Using `<tr>` and `<td>` tags along with `{{#each}}` helper should be avoided as it breaks the markup of the *contenteditable* element. Use the *iterate* attribute instead.\n\nWith *iterate* attribute (as of v8.2):\n\n```html\n<table style=\"width: 100%;\">\n  <tbody>\n    <tr iterate=\"{{contacts}}\">\n      <td>{{name}}</td>\n      <td>{{assignedUserName}}</td>\n    </tr>\n  </tbody>\n</table>\n```\n\nDisplaying certain number of items in one row:\n\n```\n{{#each contacts}}\n   {{#ifMultipleOf @key 3}}<br>{{/ifMultipleOf}}{{name}} \n{{/each}}\n```\n\n!!! important\n\n    The scope is changed inside an iteration block. To access parent scope attributes, use `../`.\n\nAccess the parent scope:\n\n```\n{{#each contacts}}\n    Root record name: {{../name}}\n    Contact name: {{name}}\n{{/each}}\n```\n\n### Lookup\n\nYou can use this helper to access object's and array's items.\n\nIn object (map):\n\n```\n{{lookup map key}}\n```\n\nIn an array:\n\n```\n{{lookup teamsIds index}}\n```\n\nLink-multiple example:\n\n```\n<p iterate=\"{{teamsIds}}\">{{lookup ../teamsNames this}}</p>\n```\n\n### Expressions\n\n* `{{object.key}}` – lookup in objects;\n* `{{array.[0]}}` – lookup in arrays;\n* `{{~anyTag}}` – remove all previous spacing;\n* `{{anyTag~}}` – remove all next spacing;\n* `{{{helper}}}` – prevent escaping;\n* `{{helper1 (helper2  arg1 arg2) arg2 arg3}}` – sub-expression passed as an argument;\n\n### Logical expressions\n\n*As of 8.4.*\n\nHelpers:\n\n* and\n* or\n* not\n\nTo be used in sub-expressions.\n\nExamples:\n\n```\n{{#if (or (equal status 'Draft') (equal status 'Active'))}}\n    ...\n{{/if}}\n```\n\n```\n{{#if (and value1 value2 value3)}}\n    ...\n{{/if}}\n```\n\n### Images\n\n```\n{{imageTag imageFieldNameId width=50 height=50}}\n```\n\n* *imageFieldNameId* is a name of image field, concatenated with *Id*\n* *width* and *height* can be omitted\n\nAnother legacy way to print images:\n\n```\n<img src=\"{{file imageFieldNameId}}\">\n```\n\nwhere `imageFieldNameId` – the name of an image field, concatenated with the suffix *Id*.\n\n\n### Date & time formatting\n\nSee info about [date formatting](../administration/date-formatting.md).\n\nFormat *Date-Time* field:\n\n```\n{{dateFormat createdAt_RAW format='MMMM DD, YYYY' timezone='Europe/London'}}\n```\n\nFormat *Date* field:\n\n```\n{{dateFormat closeDate_RAW format='YYYY MMMM DD'}}\n```\n\nPrint formatted *now*:\n\n```\n{{dateFormat now_RAW format='MMMM DD, YYYY HH:mm'}}\n```\n\nPrint formatted *today*:\n\n```\n{{dateFormat today_RAW format='MMMM DD,YYYY'}}\n```\n\nSpecific language:\n\n```\n{{dateFormat createdAt_RAW format='MMMM DD' language='de_DE'}}\n```\n\n### Number formatting\n\nTo display float numbers without a fractional part (as integer), use the following expression:\n\n```\n{{numberFormat quantity_RAW decimals=0}}\n```\n\nWhere `quantity` is a field name.\n\nCustom formatting for currency values:\n\n```\n{{numberFormat unitPrice_RAW decimals=2 decimalPoint=',' thousandsSeparator=' '}}\n```\n\nValue `10000.5` will be printer as `10 000,50`.\n\nNote that `_RAW` is appended to the field name.\n\n### Currency symbol\n\nA ready value prepared for all currency fields:\n\n```\n{{amountCurrencySymbol}}\n```\n\nUsing a helper (as of v9.3):\n\n```\n{{currencySymbol 'USD'}}\n```\n\nExample for a currency field named *amount*:\n\n```\n{{currencySymbol amountCurrency}}\n```\n\nwhere `amount` is a field name (of *currency* type).\n\n### Text field\n\nTo display text fields (multi-line) use triple braces:\n\n```{{{description}}}```.\n\nPrint Markdown (as of v8.1):\n\n```\n{{markdownText fieldName_RAW}}\n```\n\n### Related records\n\n*Many-to-many and one-to-many.*\n\nIt's possible to loop through a link collection.\n\nThe maximum number of records is 100. It can be changed with a config parameter *htmlizerLinkLimit*.\n\n!!! example\n\n    Printing contact names and roles of an opportunity:\n\n    ```\n    {{#each contacts}}\n        Name: {{name}},\n        Role: {{opportunityRole}},\n        Contact's Account Type: {{account.type}}\n    {{/each}}\n    ```\n\n    Where *contacts* is a relationship name. You can obtain relationship names at Administration > Entity Manager.\n\n\n!!! example\n\n    Example, printing contact names of an opportunity:\n\n    ```\n    {{#each contactsIds}}\n        {{var this ../contactsNames}}\n    {{/each}}\n    ```\n\n### Multi-enum & Array fields\n\nPrinting selected items:\n\n```\n{{#each fieldName}}\n   {{./this}}\n{{/each}}\n```\n\n### Checklist field\n\n```\nOption 1: {{checkboxTag fieldName option='Option 1' color='blue'}}\nOption 2: {{checkboxTag fieldName option='Option 2' color='blue'}}\nOption 3: {{checkboxTag fieldName option='Option 3' color='blue'}}\n```\n\n### Barcode field\n\n```\n{{barcodeImage barcodeField_RAW type='EAN8' width=60 height=30 fontsize=14 text=true padding=0}}\n```\n\nWhere *barcodeField* is the name of your barcode field.\n\nParameters *fontsize*, *text*, and *padding* are supported only in the TCPDF engine.\n\n(TCPDF only)\n\nAvailable types:\n\n* CODE128\n* CODE128A\n* CODE128B\n* CODE128C\n* EAN13\n* EAN8\n* EAN5\n* EAN2\n* UPC\n* UPCE\n* ITF14\n* pharmacode\n* QRcode\n\n### Raw values\n\nTo access a raw value of a specific attribute, you need to add a suffix  `_RAW` to the attribute name. The raw value is a not formatted value. Raw date-time values are strings with values in the UTC timezone.\n\n!!! example\n\n    Example (applying another format to the raw value):\n\n    ```\n    {{numberFormat quantity_RAW decimals=0}}\n    ```\n\n    *quantity* is a field name.\n\n### Maps\n\nIt's possible to print Google Maps image in PDF. See [here](../administration/maps.md#printing-in-pdf).\n\n### Custom helpers\n\nSee how to create custom helpers [here](../development/template-custom-helper.md).\n\nHelpers can be useful when the same part is used throughout many templates, for example, a header or footer. Printing of such parts can be delegated to a helper.\n\nHelpers can be also used for data formatting.\n"
  },
  {
    "path": "docs/user-guide/products.md",
    "content": "# Products\n\nThe Products feature is available in the [Sales Pack](https://www.espocrm.com/extensions/sales-pack/) extension.\n\nProducts can be added as line items in Quotes, Sales Orders, Invoices, Credit Notes, Delivery Orders, Receipt Orders, Purchase Orders, and Opportunities.\n\nThe *Product* entity type is available for customization in the Entity Manager. You can add custom fields to the Product as well as custom relationships between the Product and other entity types.\n\nA product record has 3 price fields: *Cost*, *List* and *Unit*. The list and unit prices are available only if product-level prices are enabled (in settings). There is the ability to automatically calculate the *Unit Price* using different formulas according to a selected *Pricing Type*. Prices can also be defined in Price Books. Note that it’s possible – and often advisable – to define prices exclusively in Price Books while leaving the list and unit price fields in the product record empty.\n\nProducts can be associated with Tax Classes, enabling automated tax application based on defined tax rules. Whenever a product is added to a document, the appropriate tax will be applied to the item.\n\nWith the Inventory Management feature enabled, you can track the availability of each product item. The *Is Inventory* field must be checked in the product record to enable inventory tracking.\n\nProducts can be printed to PDF. See more detail [here](quotes.md#templates).\n\nThe ability to add products as line items of an Opportunity is disabled by default. An administrator needs to add the *Items* panel under Administration > Entity Manager > Opportunity > Layouts > Bottom panels.\n\nIn this article:\n\n* [Categories](#categories)\n* [Variants](#variants)\n* [Properties](#properties)\n\n## Categories\n\nEach product can be linked to a category. Categories can be arranged in a hierarchical tree structure, where each category may include subcategories.\n\nThe Product Category is a separate entity type. Access to it is controlled by Roles.\n\n![Categories](../_static/images/user-guide/products/categories.png)\n\n## Variants\n\n*As of Sales Pack v2.0.*\n\n### Product Attributes\n\nBefore being able to create products with variants, you need to create some Product Attributes. Product attributes are available under: Products > the top-right menu > Product Attributes.\n\nEvery product attribute is supposed to have a specific set of options. Add needed options on the Product Attribute detail view.\n\nExamples of attributes with their options:\n\n* Size – XS, S, M, L, XL\n* Color – Red, Blue, White, Black\n\n### Template Products\n\nA Template Product serves as a root for variants. Product variants inherit properties of its template, some properties can be overridden in variants.\n\nTo create a product with variants you need to create a template product. Click **Create Product** from the **Products** page, select *Template* **Type**. Then, in the **Template** tab, add needed attributes. For every attribute, select options needed options. Then **Save** the Product.\n\nAfter that, you need to generate variants. From the template product detail view, open the **Variants** tab in the bottom, click **Generate**. It will generate all possible combinations according to attributes and options of the product template.\n\nYou can remove variants that you don't need. E.g. a Red shirt is not produced in the XS size, hence, you need to remove the XS-Red variant.\n\nYou can re-generate variants. It will create all missing combinations.\n\n!!! important\n\n    Once a product variant is references somewhere in the system (e.g. in a sales order), you should not remove that variant. Otherwise, after you re-generate it, it will be a different product record with a different ID.\n\n    For the same reason, it's not recommended to add additional attributes to product templates, variants of which are already referenced.\n\n### Miscellaneous\n\nWhen you select a template product (e.g. in a Quote), a modal dialog will appear prompting to select a specific variant.\n\nInventory quantity is tracked on the variant level. When viewing the quantity of a Template product, the sum of all variants will be shown.\n\nAn Inventory Number cannot be associated with a Product Template. It should be associated with a specific Variant.\n\nIt's possible to specify Product fields that should be **synced** between Template and Variants. Administration > Entity Manager > Products > Edit > Variant sync fields. These fields will be read-only in Variants. Whenever the field value is changed in the Template, it will be automatically copied to the Variants. By default, the *Status* field is selected as synced.\n\n## Properties\n\nA product can marked as Sellable, Purchasable, or Subscribable.\n\n### Item Type\n\n*As of v4.0.*\n\nTwo options are available: Goods or Services. If Goods is selected, the product can be used in deliveries, receipts, and transfers, and it allows inventory tracking.\n\n### Allow Fractional Quantity\n\nIf enabled, it will be possible to use fractional quantity values for a product.\n\n### Track Inventory\n\nAvailable if the *Inventory Transactions* feature is enabled in the system. If the *Track Inventory* parameter is disabled in a product, its quantity won't be tracked.\n\nNote: In the earlier versions this parameter was called *Is Inventory*.\n\n### Inventory Number Type\n\nCan be empty, Batch or Serial. See more about inventory numbers [here](../extensions/sales-pack/inventory-management.md#inventory-numbers).\n\n### Removal strategy\n\nAvailable if *Inventory Number Type* is not empty. Determines how Inventory Numbers will be sorted when a user picks a number for a delivery or transfer order.\n\nAvailable options:\n\n* FIFO – first in, first out; sorted by *Incoming Date* in ascending order;\n* FEFO – first expired, first out; sorted by *Expiration Date* in ascending order;\n* LIFO – last in, first out; sorted by *Incoming Date* in descending order.\n\n### Expiration Days\n\nAvailable if *Inventory Number Type* is not empty. A number of days that is automatically added to the current date to determine an *Expiration Date* of an Inventory Number when the number is created in the system. Note that the Expiration Date then can be changed by a user.\n\n### Tax Classes\n\nTax classes allow the system to automatically select an appropriate Tax Code for a product. For example, a product can have a tax class named 'Zero-rated'. A tax item rule will map this tax class to a tax code with a zero rate. Then, every time the product is added to a document line, that tax code will be automatically set.\n"
  },
  {
    "path": "docs/user-guide/quotes.md",
    "content": "# Quotes\n\nThe Quotes feature is available in [Sales Pack](https://www.espocrm.com/extensions/sales-pack/).\n\nA quote is a formal pricing document that outlines specific products or services, along with their quantities and associated prices, offered to a customer.\n\nThe Quote entity type has a relationship with Opportunity type. You can add the *Quotes* panel to the Opportunity detail view at Administration > Layout Manager > Opportunities > Bottom Panels. When creating a new quote linked to an opportunity, it transfers opportunity items to the quote.\n\nYou can add the Quotes panel to the Account detail view to be able to see related quotes: Administration > Layout Manager > Accounts > Bottom Panels.\n\nIn the article:\n\n* [Converting from Opportunity](#converting-from-opportunity)\n* [Generating Sales Orders and Invoices from Quote](#generating-sales-orders-and-invoices-from-quote)\n* [Total values layout](#total-values-layout)\n* [Quote Items](#quote-items)\n* [Printing to PDF](#printing-to-pdf)\n* [Sending in email](#sending-in-email)\n* [Automatic numbering](#automatic-numbering)\n* [Copying values from product to quote item](#copying-values-from-product-to-quote-item)\n* [Locking](#locking)\n* [Automation with Workflows or BPM](#automation-with-workflows-or-bpm)\n\n## Converting from Opportunity\n\nMethod 1. Create a new quote, on the form, specify a needed opportunity. Data will be copied from the opportunity to the created quote.\n\nMethod 2. Create a new quote from Quotes relationship panel on the detail view of the opportunity. Note: The administrator needs to add the panel in the Layout Manager.\n\n## Generating Sales Orders and Invoices from Quote\n\nYou are able to create a Sales Order and an Invoice from an existing Quote.\n\nMethod 1. Create a new sales order or invoice, on the form, specify the needed quote. Data will be copied from the quote to the created sales order or invoice.\n\nMethod 2. Create a new sales order or invoice from the corresponding relationship panel on Quote detail view.\n\n## Total Values Layout\n\nThe layout of total value fields (in the bottom on detail view) can be modified at Administration > Layout Manager > Quotes > Bottom Total.\n\n## Quote Items\n\nA Quote has a list of items. Each item can represent a certain product or a service with description, quantity, tax rate, list price, and unit price fields. It's possible to sort items manually.\n\nThere is the ability to add custom fields for the Quote Item entity type using the Entity Manager.\n\n### Quote Items layout\n\nThe layout of quote items can be modified at Administration > Layout Manager > Quote Items > List (Item).\n\n### Discount Rate\n\nIt's possible to specify a discount in percents. To have this ability, the administrator should add the  *Discount (%)* field to the *List (Item)* layout.\n\n## Printing to PDF\n\nQuotes can be printed to PDF. This action is available in the dropdown next to Edit button on the quote’s detail view. Then, you will be prompted to select a Template. More info about printing to PDF is available [here](printing-to-pdf.md).\n\n### Templates\n\nAn example template is available by default. You can create new templates (Quotes list view > top-right dropdown menu > Templates) as well as edit existing ones.\n\nFor more precise template editing, you can use the Code View mode.\n\nYou can print fields ofa  Quote record as well as fields of related records by utilizing placeholders in your template.\n\nExamples:\n\n`{{accountName}}` – Account name,\n\n`{{{billingAddressStreet}}}` – street,\n\n`{{account.type}}` – type of related Account,\n\n`{{assignedUser.lastName}}` – last name of the assigned user.\n\nIf your line item is a product, you can print product’s fields.\n\nExamples:\n\n`{{product.length}}`,\n\n`{{product.color}}`.\n\nIn examples, the length and color are custom fields of the Product entity type.\n\nLooping through quote items:\n\n```\n<tr iterate=\"{{itemList}}\">\n  <td>{{order}}</td>\n  <td>{{name}}</td>\n  <td>{{quantity}}</td>\n  <td>{{product.weight}}</td>\n  <td align=\"right\">{{listPrice}}</td>\n  <td align=\"right\">{{unitPrice}}</td>\n  <td align=\"right\">{{amount}}</td>\n</tr>\n```\n\nOr:\n\n```\n<!-- {{#each itemList}} -->\n  <td>{{order}}</td>\n  <td>{{name}}</td>\n  <td>{{quantity}}</td>\n  <td>{{product.weight}}</td>\n  <td align=\"right\">{{listPrice}}</td>\n  <td align=\"right\">{{unitPrice}}</td>\n  <td align=\"right\">{{amount}}</td>\n<!-- {{/each}} -->\n```\n\nIt's possible to print image fields:\n\n```\n<img src=\"{{file imageId}}\">\n```\n\nWhere `imageId` – the name of the custom image field concatenated with the suffix `Id`.\n\nFor product line item:\n\n```\n<img src=\"{{file product.photoId}}\">\n```\n\nTo display float numbers (like quantity, unitPrice etc.) without a fractional part (as integer), use the following expression:\n\n```\n{{numberFormat quantity_RAW decimals=0}}\n```\n\nCustom formatting for currency values:\n\n```\n{{numberFormat unitPrice_RAW decimals=2 decimalPoint=',' thousandsSeparator=' '}}\n```\n\nValue `10000.5` will be printer as `10 000,50`.\n\nTo display text fields (multiline), use triple braces: `{{{description}}}`.\n\n#### Quote Items attributes\n\nYou can use these attributes in a template inside the loop `{{#each itemList}}` or `<tr iterate=\"{{itemList}}\">`:\n\n* name\n* quantity\n* listPrice\n* unitPrice\n* discount\n* amount\n* unitWeight\n* weight\n* taxRate\n* order\n* description\n\nAll fields can be found at Administration > Entity Manager > Quote Items > Fields.\n\n## Sending in email\n\nA Quote PDF can be sent in an email as an attachment. Open a quote record, click the dropdown next to Edit button, and then click Email PDF.\n\nThe default email template can be set by the administrator: Administration > Sales Pack Settings > Email Templates.\n\nTo have the Quote entity selected as the email's parent, the administrator should add the Quote entity type to the parent type list. Administration > Entity Manager > Email > Fields > Parent > Entity List. As of v3.0.\n\n## Automatic numbering\n\nBy default, the *Number* field is auto-incremented. You can disable auto-increment at Administration > Entity Manager > Quote > Fields > number. It's also possible to make the number field read-only.\n\nThe prefix of the next number, the next number itself and the quantity of digits in the number can be configured at Administration > Entity Manager > Quote > Fields > numberA.\n\nBy default, there is no *Name* field on the *Detail* layout. The *Number* is used as a name. You can add the Number field at Administration > Entity Manager > Quote > Layouts > Detail.\n\nBy default, the *Name* field is synced with *Number*. To be able to specify arbitrary names, you need to disable the *Sync with Number* and *Read-only* parameters at Administration > Entity Manager > Quote > Fields > Name.\n\n## Copying values from product to quote item\n\nField values can be transferred from a product to a quote item upon product selection. Field names you want to be copied should coincide in Product and Quote Item entity type.\n\nYou can select which fields you need to be copied at Administration > Entity Manager > Quote Item > Fields > Product > Fields to Copy.\n\n## Locking\n\nA Quote can be locked if it's completed or canceled. When a record is locked, a specific fields become read-only. An administrator can configure the field list at: Administration > Entity Manager > Quote > Edit.\n\nIf the settings parameter *Forbid order unlocking* is checked, once a record is locked, it can be unlocked only by an administrator.\n\n## Automation with Workflows or BPM\n\nThe following service actions are available in Workflows and BPM tools:\n\n* Add Quote Items\n* Convert Currency\n* Send in Email\n\n## See also\n\n* [Custom calculations for Quote totals](../development/quote-custom-calculations.md)\n"
  },
  {
    "path": "docs/user-guide/reports.md",
    "content": "---\nsearch:\n  boost: 2\n---\n\n# Reports\n\nThe Reports feature is available in [Advanced Pack](https://www.espocrm.com/extensions/advanced-pack/). It provides the analytic capabilities and two additional functionalities: report panels and custom list view filters.\n\nThere are three types of reports:\n\n* List\n* Grid\n* Joint Grid\n\nIn this article:\n\n* [List reports](#list-reports)\n* [Grid reports](#grid-reports)\n* [Joint Grid reports](#joint-grid-reports)\n* [Filters](#filters)\n* [Displaying on dashboard](#displaying-on-dashboard)\n* [Email sending](#email-sending)\n* [Printing to PDF](#printing-to-pdf)\n* [Syncing with Target Lists](#syncing-with-target-lists)\n* [List view filters based on reports](#report-filters)\n* [Reports panels](#report-panels)\n* [Portal access](#portal-access)\n* [Formula functions](#formula-functions)\n\nSee also:\n\n* [Complex expressions](complex-expressions.md)\n* [Quick tour](https://app.supademo.com/demo/cmca8j4uc1gy18qszrhdt68jy)\n\n\n## List Reports\n\nA List report displays the list of records that meet the specified criteria.\n\nTo create a new list report, click on the *Reports* tab and then click the *Create Report* button. Then, select the entity type to which your report will apply.\n\nIn the *Columns* field, select the fields you would like to have displayed in the report. Underneath, you can configure how each column is displayed with the following parameters:\n\n* Width – width in percents;\n* Align – how to align data: left or right;\n* Link – value will be displayed as a link leading to the record detail view;\n* Export Only – the column won't be displayed in report results on the UI, but it will be available in export;\n* Not Sortable – the column cannot be ordered by, some fields are not available for sorting;\n* Hidden – the column will be hidden but can be optionally shown in the report result view.\n\nChoose the needed sorting in the *List Order* field.\n\nIn the *Filters* section, you can specify criteria that determine what records will be included in your report. You can use logical operators 'OR' and 'AND' here.\n\n*Runtime Filters* lets you narrow down the results each time you run the report, without needing to edit the report itself. It's useful when the report structure stays the same, but you want to change the criteria dynamically – like choosing a specific date range, customer, or status before generating the results.\n\nYou can *export* list report results to XLSX (spreadsheet) and CSV formats.\n\nAn example of list report results:\n\n![List report example](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/list.png)\n\nWhere list reports can be also utilized:\n\n* Scheduled workflows – to do some scheduled actions over records that met criteria specified by a list report.\n* Scheduled BPM processes – to start BPM processes for records that met some criteria.\n* Sync with target lists – to add records that met some criteria to target lists, more info [below](#syncing-with-target-lists).\n* List view filters – to filter records on the list view according to the criteria specified in the list report, more info [below](#report-filters).\n* Panels on the detail view – to display related records that met some criteria on the side panel, more info [below](#report-panels).\n* Applying assignment rule – to assign records that met specific criteria by workflow or BPM.\n\n### Results view\n\nThe results view can be accessed under: Report detail view > Results View button (top-right corner). Here, the report is displayed in full width. You can show or hide specific columns as well as resize them.\n\n## Grid Reports\n\nGrid reports display summarized values, can be grouped by one or two fields, and support chart visualization.\n\nTo create a new grid report, click on the *Reports* tab and then click the *Create Report* button. Then, select the entity type to which your report will apply.\n\nWhen choosing the *Entity Type* for a grid report, consider the following. The *Entity Type* should contain the field that data will be aggregated by. For example, if you need to sum by the opportunity amount, choose the Opportunity entity type. If you need to aggregate by fields from different entity types, consider creating separate grid reports for each entity type and then use a Joint Report to join them into one.\n\nAn example of grid report results showing revenue grouped by a user:\n\n![Grid report example](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/grid.png)\n\n!!! tip\n\n    When dealing with long tables with many columns, you can use Shift + Mouse Wheel to scroll horizontally. It can also be helpful to use the Result View, which displays the report data in full width.\n\n### Group By\n\nIn the *Group By* field, pick one or two fields you want your report data be grouped by. For date fields, it's possible to apply grouping by year, quarter, month, week, and day. If you leave the Group By field empty, the report will not apply any grouping.\n\nThere is the ability to craft a [complex expression](complex-expressions.md) for grouping. Complex expressions are internally translated into SQL statements. Complex expressions offer various use cases. For instance, the MAP function can be used to group data by region rather than by country.\n\nExample:\n\n```\nMAP:(\n    account.billingAddressCountry,\n    'United States', 'United States',\n    'Germany', 'Europe',\n    'France', 'Europe',\n    'Italy', 'Europe',\n    'Other'\n)\n```\n\nA report grouped by two fields is called *two-dimensional*.\n\nThe results table for two-dimensional Grid reports can be displayed in two modes:\n\n- Regular – columns represent the first grouping field, and rows represent the second grouping field.\n- Normalized – unpivoted (flattened), with both grouping fields displayed in rows.\n\n### Columns\n\nIn the *Columns* field, select one or more **aggregate** functions applied to a specific field.\n\nFunctions:\n\n* COUNT – number of records;\n* SUM – summation, applied to Currency, Int and Float fields;\n* MIN – minimal value;\n* MAX – maximal value;\n* AVG – average value.\n\nIf a report is grouped by a link field, then it's possible to include fields from the linked record without an aggregate function applied to it. In the example below, the report for Opportunities with grouping by Campaign with Campaign.Budget column included.\n\nIt's possible to add **non-aggregated columns**. In this case, records will be displayed for each group. Note that if your report deals with a big number of records, it can run much slower.\n\nNon-grouping grid report with non-aggregated columns:\n\n![Grid list non-grouping](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/grid-list-0.png)\n\nGrouping grid report with non-aggregated columns:\n\n![Grid list grouped](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/grid-list-1.png)\n\nThere is the ability to craft [complex expressions](complex-expressions.md) for columns. Complex expressions are internally translated into SQL statements.\n\n### Order by\n\nThe *Order By* field defines how the report results will be sorted.\n\n### Filters section\n\nIn the *Filters* section, you can specify criteria to limit data displayed in the report results. You can use logical operators 'OR' and 'AND' here. See more info [below](#filters).\n\n### Runtime filters\n\n*Runtime Filters* lets you narrow down the results each time you run the report, without needing to edit the report itself.\n\n!!! note\n\n    Specifying a runtime filter can be also useful for dashlets and report panels. It allows you to have filters applied to a particular dashlet or panel.\n\n### Charts\n\nGrid report allows displaying results in chart form.\n\nThere are the following chart types available:\n\n* Bar (Horizontal);\n* Bar (Vertical);\n* Bar Grouped (Horizontal) (only for report with grouping by 2 columns);\n* Bar Grouped (Vertical) (only for report with grouping by 2 columns);\n* Pie (only for report with grouping by 1 column);\n* Line.\n\nBar:\n\n![Bar](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/chart-bar.png)\n\nBar Grouped:\n\n![Bar grouped](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/chart-bar-grouped.png)\n\nLine:\n\n![Line](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/chart-line.png)\n\nPie:\n\n![Pie](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/chart-pie.png)\n\n### Export\n\nIt's possible to export grid report results to XLSX (spreadsheet) and CSV formats. Both a results table and chart are exported to XLSX.\n\n!!! important\n\n    If a Grid report contains non-aggregated columns, the chart is not printed on the spreadsheet.\n\n### Access\n\nBy checking *Apply access control*, the report result will not include records that the current user does not have access to.\n\nIf a regular user does not have edit access to the *Apply access control* field (via field level security in Roles), all reports they create will have the *Apply access control* automatically checked.\n\n## Joint Grid reports\n\nJoint Grid reports combine multiple Grid reports. A combined report can bring together data from reports that target different entity types.\n\nGrid reports selected for a Joint report must use either one grouping field or none.\n\nIf you need to aggregate by fields from different entity types, consider creating separate Grid reports for each entity type and then use the Joint report type to combine them into one.\n\nSome usage examples:\n\n* Lead count / Contact count;\n* Revenue by month / Campaign Budget by month;\n* Revenue by user / Lead count by User.\n\nYou can create a new Joint Grid report from the dropdown menu in the top-right corner in the Reports list view.\n\nColors of chart columns are determined by chart colors set in the respective sub-reports.\n\nRuntime filters are not supported in Joint reports. Only regular filters specified in each sub-report can be used.\n\nNon-aggregate columns are not supported in Joint reports.\n\n## Filters\n\n### Field filter\n\nField filters are simple to use. They allow to filter by specific fields of a target entity type as well as fields of related records. For example, you can filter Opportunities by a field of the Account entity type.\n\n![Field filter](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/filter-field.png)\n\n### OR group\n\nOR means that at least one condition in the group must be met.\n\n![OR group](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/filter-or.png)\n\n### AND group\n\nAND means that all conditions in the group must be met.\n\n### NOT IN group\n\nNOT IN provides the ability to filter records that don't meet specified criteria. E.g. listing accounts that don't have any opportunity with 'Closed Won' or 'Closed Lost' status.\n\n!!! note\n\n    It's recommended to avoid using NOT IN group when possible, by using filters 'Not Equals', 'None of', etc. instead. NOT IN group uses a sub-query that can negatively affect report performance in some cases.\n\n![NOT IN group](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/filter-not.png)\n\n### IN group\n\nIN is similar to AND group but utilizes a sub-query.\n\nThe example of usage: Filtering accounts that have opportunities of both 'Closed Won' and 'Negotiation' stages.\n\n![IN group](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/filter-in.png)\n\n### Complex Expression\n\nFor more advanced use. You can apply a database function to a certain database column and compare it with a result calculated by a [formula](../administration/formula.md) expression.\n\n!!! note\n\n    If you need to compare just with a simple string value you should put it into single quotes `'some string'`.\n\n!!! note\n\n    Formula functions intended to interact with the entity record will not work here because the formula is not applied to a specific record.\n\nApplying function to a column and comparing with a result of formula:\n\n![Complex Expression filter](../_static/images/user-guide/reports/filter-complex.png)\n\nComparing the result of the custom complex expression and the result of the formula expression:\n\n![Complex Expression filter](../_static/images/user-guide/reports/filter-complex-expression.png)\n\n* Complex expression is translated into an SQL statement and becomes a part of an SQL query.\n* Formula is executed before running the report and the result value is substituted into an SQL query.\n* Comparison operator is substituted into an SQL query between the complex expression statement and the formula result value.\n\nMore info about complex expressions is available [here](complex-expressions.md).\n\n!!! example\n\n    Filter record that were created after less than 12 month from the creation of a related account. For example, it can be used to show sales only from new customers.\n\n    ```\n    LESS_THAN:(\n        TIMESTAMPDIFF_MONTH:(\n            account.createdAt,\n            createdAt\n        ),\n        12\n    )\n    ```\n\n### Having group\n\nThe Having group provides the ability to filter records with using aggregate functions COUNT, SUM, MAX, MIN, AVG.\n\nSome use cases:\n\n* List of accounts having more than one opportunity. `COUNT / opportunities.id / Greater Than / 1`.\n* Grid report showing accounts grouped by industry where revenue is more than 1,000. `SUM / opportunities.amount / Greater Than / 1000`.\n\n## Displaying on dashboard\n\nYou can display any report on the dashboard. In order to do it, you need to add the Report dashlet to the dashboard and then pick the needed report from the dashlet options.\n\nFor grid reports it's possible to display:\n\n* Chart\n* Chart & Total\n* Total\n* Table\n\nFor list reports it's possible to display:\n\n* List\n* Total (number or records)\n\nFor list reports, you can either display the list or records or only the total number of records.\n\nDashlet with only totals displayed:\n\n![Dashlet with totals](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/reports/dashlet-totals.png)\n\n## Email sending\n\nIt's possible to set up the system send report results to certain users on a regular basis according to specified time. This must be configured for certain reports individually.\n\nThe Max number of records that can be sent in an email by default is set to 3000. You can increase it by adding the parameter to data/config.php: `'reportSendingListMaxCount' => 5000`.\n\n## Printing to PDF\n\n!!! note\n\n    A user needs to have access to the *Template* scope in Roles.\n\n    You need to have at least one PDF Template record for the Report entity type. The template can be created at Administration > PDF Templates.\n\nTo print a Report: on the Report detail view on the *Report* panel, from the dropdown next to the *Edit* button, click *Print to PDF*.\n\nIn a PDF template, `{{reportTable}}` helper is used to print a report results table.\n\nExample:\n\n```\n{{reportTable border=1 borderColor=\"#333\" cellpadding=2 fontSize=9}}\n```\n\nAvailable attributes:\n\n* border – a border with;\n* borderColor;\n* cellpadding;\n* fontSize;\n* color – a text color;\n* flip – to flip table, true or false;\n* width – a table width, a CSS parameter (as of v3.1).\n\n## Syncing with Target Lists\n\nIt's possible to have target lists synced with list report results. It's convenient for mass email when you would like to send emails only to contacts that meet some criteria at the moment of sending. This feature is available in the detail view of any target list in the *Sync with Reports* panel.\n\n## Report filters\n\nThe Report Filters feature allows you to create custom primary filters for list views. These filters can also be used in specific formula functions.\n\nAn administrator can create custom list view filters based on specific reports. Available under: Administration > Report Filters. It's possible to specify teams that will have access to the filter.\n\n!!! note\n\n    The layout, that is specified in the report, is not applied to the list view when the filter is selected.\n\n![Report filter](../_static/images/user-guide/reports/report-filter.png)\n\nReport filters can utilized in *Record List* dashlets (as a primary filter).\n\nReport filters can be utilized in [formula functions](../administration/formula.md#filter):\n\n* `record\\count`\n* `record\\findOne`\n* `record\\findRelatedOne`\n* `record\\findRelatedMany`\n* `entity\\sumRelated`\n* `entity\\countRelated`\n\n## Report panels\n\nThe Report Panels feature allows you to create custom detail view panels that display report results.\n\nAn administrator can create custom side and bottom panels for the detail view of the specific entity type. It's possible to specify teams that will have access to the panel.\n\nBoth Grid and List reports can be used.\n\nFor grid reports it's possible to display:\n\n* Chart\n* Chart & Total\n* Total\n* Table (as of v2.7.0)\n\nFor list reports it's possible to display:\n\n* List\n* Total (number or records)\n\nThe order of side panels can be customized under: Administration > Entity Manager > {Entity Type} > Layouts > Side Panels (Detail).\n\nThe order of bottom panels can be customized under: Administration > Entity Manager > {Entity Type} > Layouts > Bottom Panels.\n\nThe report panel displays results related to the record that is viewed. The first found relationship is used. If a report has an appropriate runtime filter, then it will be used to filter report results. The runtime filter must be a field of a Link, Link-multiple or Link-parent type. \"For example, if a report is for Opportunity and has a runtime filter Account, that filter will be automatically applied when the report panel is added to the Account detail view.\n\n## Portal access\n\nSpecific reports can be allowed for specific portals. For this, you need to add the portal in the *Portals* field of the Report. The Portal Role assigned to the portal should have defined access to the *Reports* scope with the *Read* action set to *all*.\n\nIt's possible to add a report dashlet to the portal dashboard.\n\n!!! note\n\n    For grid reports which are meant be available in the portal, it's usually reasonable to enable [Apply ACL](#access).\n\n## Formula functions\n\n### report\\export\n\n`report\\export(REPORT_ID, [USER_ID])`\n\n*As of v3.6.*\n\nGenerates an XLSX export file and returns an attachment ID. An optional USER_ID allows you to apply access restrictions for a specific user. Note that generated attachments have the role `Export File`, hence they will be automatically deleted by the cleanup job. To prevent deletion, you can change the role to `Attachment`.\n\n## See also\n\n* [Complex expressions](complex-expressions.md)\n* [Billing transactions](https://www.espocrm.com/blog/tutorial-billing-transactions/)\n"
  },
  {
    "path": "docs/user-guide/sales-management.md",
    "content": "# Sales Management\n\nIn this article:\n\n* [Leads](#leads)\n* [Opportunities](#opportunities)\n* [Accounts](#accounts)\n* [Currency](#currency)\n* [Sales analytics](#sales-analytics)\n* [See also](#see-also)\n\n## Leads\n\nA Lead represents a person or organization that  is not currently a customer but has the potential to be. Creating a new Lead record is usually the first step in the sale process. As more information about the Lead is gathered,  the Lead is expected to be converted into an Account, Contact, and/or Opportunity.\n\nNew Leads are typically created in the following scenarios:\n\n* manually by CRM users;\n* through the API (e.g. through a web form);\n* automatically by a Workflow rule.\n\nBy utilizing the [Workflows](../administration/workflows.md) tool, an administrator can set up the system to apply a specific assignment rule to new Leads. *Round-Robin* and *Least-Busy* rules are available. For more complex business flows, it's recommended to utilize the [BPM tool](../administration/bpm.md).\n\nUsers can also create a Lead from an Email – from the top-right dropdown menu.\n\nTo prevent overlooking of new Leads, users can add the *Lead* entity type to the *Global Auto-follow* list in Preferences. Then, they will automatically follow every new Lead created in the system they have access to.\n\nIt may be useful to enable the Kanban view for Leads. It can be enabled under: Administration > Entity Manager > Lead > Edit > Kanban View.\n\n### Target lists\n\nLeads can be added to Target Lists, which is useful for both marketing and organizing purposes. A user can use the Target Lists filter in the Leads list view to segment leads by the selected target list for further processing.\n\n### Converting\n\nTo convert a Lead, you need to click *Convert* button on the Lead detail view. Then, you can check to what record types you want to convert: Account, Contact, and/or Opportunity.\n\nA converted Lead won't be removed from the system. It will have status *Converted*, records it was converted to, will be available in the *Converted To* panel on the right.\n\nNote that Leads cannot be converted to Accounts if the system is set to the B2C mode.\n\n## Opportunities\n\nAn Opportunity represents a potential deal or closed sale.\n\n!!! note\n\n    Opportunities with the *Closed Won* stage are taken into account in the default sales dashlets. Using Opportunities to calculate revenue is an option that may be suitable for small businesses.\n\nFor Opportunities, the Kanban view is enabled by default. Users can switch between the List and Kanban views.\n\n### Stage\n\nThe following opportunity stages are available by default:\n\n* Prospecting\n* Qualification\n* Proposal\n* Negotiation\n* Closed Won\n* Closed Lost\n\nAn administrator can define custom stages depending on the business workflow of the company: Administration > Entity Manager > Opportunity > Fields > Stage. It's also possible to define custom probability values for each stage.\n\n### Probability\n\nThe Opportunity probability is an estimated percentage chance that the sale will be won. The *Closed Won* status has a 100% probability, the *Closed Lost* – zero. Other stages has their specific probabilities between 0% and 100%. The probabilities can be modified in the Entity Manager.\n\n!!! note\n\n    Probabilities can be utilized in revenue forecasting.\n\n## Accounts\n\nAccounts play a central role in EspoCRM. They represent companies and organizations your business works with.\n\nAn Account has relationships with the following records:\n\n- Contacts\n- Opportunities\n- Cases\n- Documents\n\nUsers can subscribe to a particular Account record to see updates that concern that Account.\n\nAccount records can be added to Target Lists, which you can use for marketing purposes or for organizing your data.\n\n## Currency\n\nAn administrator can define available currencies and their rates at Administration > Currency.\n\nIt's possible to convert currency of existing Opportunities:\n\n* on the list view: select needed records and then click *Convert Currency* in the *Actions* dropdown;\n* on the detail view: click the dropdown next to the *Edit* button, then *Convert Currency*.\n\n## Sales analytics\n\nThe following charts are available on the dashboard by default:\n\n* Sales by Month\n* Opportunities by Lead Source\n* Opportunities by Stage\n* Sales Pipeline\n\nBy utilizing the [Reports tool](reports.md), it's possible to view sales statistics based on specific criteria. Report charts can be displayed on the dashboard.\n\n### Revenue forecast\n\nAvailable with Reports from Advanced Pack.\n\n1. Create a new grid report for Opportunity entity type.\n2. Add 'MONTH: Close Date' to Group By field.\n3. Add 'SUM: Amount Weighted' to Columns field.\n4. Add 'Close Date' to Runtime Filters field.\n5. Select 'Bar (vertical)' chart type.\n\nThis report will show the revenue forecast based on probabilities of Opportunities.\n\nUsers who have access to this report will be able to add it on their dashboards.\n\n## See also\n\n* [Quick tour on Leads](https://app.supademo.com/demo/cmhc0w8ns14v6fatilwlycmjn)\n* [Quick tour on Opportunities](https://app.supademo.com/demo/cmhkj43rn1k3xu1hm0zxfmhb6)\n* [Quick tour on Accounts](https://app.supademo.com/demo/cmhxas59c35xb17y0s8mr6co6)\n* [Who are leads? Lead conversion in 3 steps](https://www.espocrm.com/tips/lead-conversion/)\n"
  },
  {
    "path": "docs/user-guide/sales-orders.md",
    "content": "# Sales Orders\n\nThe Sales Orders feature is available in [Sales Pack](https://www.espocrm.com/extensions/sales-pack/) extension.\n\nA Sales Order is a document representing a confirmed customer order, and contains a group of products or services with their quantities and prices.\n\nYou can add the Sales Orders panel to the Account detail view to be able to see related sales orders. At Administration > Layout Manager > Accounts > Bottom Panels.\n\nYou can add the Sales Orders panel to the Opportunity detail view at Administration > Layout Manager > Opportunities > Bottom Panels.\n\nIn the article:\n\n* [Converting from Opportunity or Quote](#converting-from-opportunity-or-quote)\n* [Generating Invoices from Sales Order](#generating-invoices-from-sales-order)\n* [Total Values Layout](#total-values-layout)\n* [Sales Order Items](#sales-order-items)\n* [Delivery](#delivery)\n* [Printing to PDF](#printing-to-pdf)\n* [Sending in email](#sending-in-email)\n* [Automatic numbering](#automatic-numbering)\n* [Copying values from product to sales order item](#copying-values-from-product-to-sales-order-item)\n* [Locking](#locking)\n* [Automation with Workflows or BPM](#automation-with-workflows-or-bpm)\n\n## Converting from Opportunity or Quote\n\nMethod 1. Create a new sales order. On the form, select an opportunity or a quote. Data will be copied from the opportunity/quote to the created sales order.\n\nMethod 2. Create a new sales order from the Sales Orders relationship panel on the detail view of the opportunity/quote.\n\n## Generating Invoices from Sales Order\n\nYou are able to create Invoices from an existing Sales Order record.\n\nMethod 1. Create a new invoice. On the form, select a needed sales order. Data will be copied from the sales order to the created invoice.\n\nMethod 2. Create a new invoice from the Invoices relationship panel on the detail view of the sales order record.\n\n## Total Values Layout\n\nThe layout of total value fields (in the bottom on detail view) can be modified at Administration > Layout Manager > Sales Orders > Bottom Total.\n\n## Sales Order Items\n\nA Sales Order has the list of items. Each item can represent a certain product or a service with description, quantity, tax rate, list price, and unit price fields. It's possible to sort items manually.\n\nThere is the ability to add custom fields to the Sales Order Item entity type using the Entity Manager.\n\n### Sales Order Items Layout\n\nThe layout of Sales Order Items can be modified at Administration > Layout Manager > Sales Order Items > List (Item).\n\n### Discount Rate\n\nIt's possible to specify a discount in percents. To have this ability, an administrator should add the *Discount (%)* field to the *List (Item)* layout.\n\n## Delivery\n\nA Delivery Order can be created from a Sales Order. A button in the top-right corner will appear when the Sales Order is eligible for delivery. The Sales Order must have at least one Product of *Goods* product type to have the ability to create a delivery. \n\n## Printing to PDF\n\nSales Orders can be printed to PDF. This action is available in the dropdown next to the Edit button on the sales order’s detail view. Then, you will be prompted to select a template. More info about printing to PDF is available [here](printing-to-pdf.md).\n\n### Templates\n\nSee the documentation [for quote templates](quotes.md#templates).\n\n## Sending in email\n\nA Sales Order PDF can be send in an email as an attachment. Open a sales order record, click the dropdown next to the Edit button and then click Email PDF.\n\nThe default email template can be set by the administrator: Administration > Sales Pack Settings > Email Templates.\n\nTo have the Sales Order entity selected as the email's parent, the administrator should add the Sales Order entity type to the parent type list. Administration > Entity Manager > Email > Fields > Parent > Entity List. As of v3.0.\n\n## Automatic numbering\n\nBy default, the *Number* field is auto-incremented. You can disable auto-increment at Administration > Entity Manager > Sales Order > Fields > number. It's also possible to make the number field read-only.\n\nThe prefix of the next number, the next number itself and the quantity of digits in the number can be configured at Administration > Entity Manager > Sales Order > Fields > numberA.\n\nBy default, there is no *Name* field on the *Detail* layout. The *Number* is used as a name. You can add the Number field at Administration > Entity Manager > Sales Order > Layouts > Detail.\n\nBy default, the *Name* field is synced with *Number*. To be able to specify arbitrary names, you need to disable the *Sync with Number* and *Read-only* parameters at Administration > Entity Manager > Sales Order > Fields > Name.\n\n## Copying values from product to sales order item\n\nField values can be transferred from a product to a sales order item upon product selection. Field names you want to be copied should coincide in the Product and the Sales Order Item entity types.\n\nYou can select which fields you need to be copied: Administration > Entity Manager > Sales Order Item > Fields > Product > Fields to Copy.\n\n## Locking\n\nA Sales Order can be locked if it's completed or canceled. When a record is locked, a specific fields become read-only. An administrator can configure the field list at: Administration > Entity Manager > Sales Order > Edit.\n\nIf the settings parameter *Forbid order unlocking* is checked, once a record is locked, it can be unlocked only by an administrator.\n\n## Automation with Workflows or BPM\n\nThe following service actions are available in Workflows and BPM tools:\n\n* Add Sales Order Items\n* Convert Currency\n* Send in Email\n\n## See also\n\n* [Custom calculations for Quote totals](../development/quote-custom-calculations.md)\n"
  },
  {
    "path": "docs/user-guide/shortcuts.md",
    "content": "# Shortcut keys\n\n*As of v7.2.*\n\n!!! note\n\n    On Mac OS, the CMD key (⌘) is the equivalent of the Ctrl.\n\n## General\n\n* `Ctrl + Middle-Click` – open a record in a quick view modal (when applied on a record link);\n\n## Record list\n\n* `Ctrl + Enter` – apply search filter;\n* `Ctrl + Space` – create new record;\n* `Ctrl + /` – focus on search-bar;\n* `Ctrl + <` – previous primary filter;\n* `Ctrl + >` – next primary filter;\n* `Ctrl + Arrow Left` – previous page;\n* `Ctrl + Arrow Right` – next page;\n\n!!! note \"Tip\"\n\n    A combination `Ctrl + Middle-Click` (on a record link) followed by `Ctrl + Space` can be used for quick edit.\n\n## Record detail\n\n* `Ctrl + Space` – switch to edit;\n* `Ctrl + \\` – switch through tabs;\n* `Ctrl + Arrow Left` – previous record;\n* `Ctrl + Arrow Right` – next record;\n\n## Record edit\n\n* `Ctrl + Enter` –  save and exit;\n* `Esc` – cancel;\n* `Ctrl + S` – save and continue editing;\n* `Ctrl + Alt + Enter` –  save and create new (from the create view);\n\n## Calendar\n\n* `Arrow Left` – previous range;\n* `Arrow Right` – next range;\n* `Home` – move to today;\n* `Minus` – zoom out (timeline);\n* `Plus` – zoom in  (timeline);\n* `1..6` – switch between view modes, refresh if the current mode;\n* `Ctrl + Space` – create event;\n\n## Image preview\n\n* `Arrow Left` – previous image;\n* `Arrow Right` – next image;\n\n## Emails\n\n* `Ctrl + Delete` – move selected emails to Trash;\n* `Ctrl + Backspace` – move selected emails to Archive (as of v8.3);\n* `Ctrl + I` – mark selected emails as Important or Not Important;\n* `Ctrl + M` – move selected emails to a specific folder;\n* `Ctrl + Q` – mark all emails as read; mark selected emails as read (as of v9.0);\n\n## Text formatting\n\n* `Ctrl + B` – bold;\n* `Ctrl + I` – italic;\n"
  },
  {
    "path": "docs/user-guide/stream.md",
    "content": "# Stream\n\nStream in EspoCRM is a feed where you can see posts and updates of records you follow. You can also post messages to your own Stream and to the Stream of other Users.\n\nBy default, the following entity types have the Stream enabled: Accounts, Contacts, Leads, Opportunities, Cases, Meetings, and Tasks. An administrator can enable or disable the Stream for a certain entity type under Administration > Entity Manager > {Entity Type} > Edit.\n\n## Record Stream\n\nThe *Stream* panel is available on the record detail view in the bottom. Posts and updates related to the record are displayed here. Each entry in the stream is represented by a *Note* entity.\n\nAn administrator can move the Stream panel down so that it will appear under other panels or put the panel into a tab. This can be done at Administration > Entity Manager > {Entity Type} > Layouts > Bottom Panels.\n\nStream posts can be pinned. A user needs to have *edit* access to a record to be able to pin or unpin Stream posts.\n\n### Access\n\nAccess to the Stream is controlled by Roles and can be configured per entity type. For example, it's possible to configure that users have access to the Stream of records related to their team.\n\nWith the [Collaborators](../administration/roles-management.md#collaborators) feature enabled, users who are record collaborators can access the Stream of the record, provided their access level, as defined by Roles, is other than *no*.\n\n## User Stream\n\nUsers can view their own Stream in the *Stream* dashlet as well on the separate Stream page.\n\nUsers can see Stream of another users on the user's detail view if they have access defined by the *User Permission* in Roles. In the user's Stream, you can see posts and updates of records that the user follows. You can also see posts addressed to that user.\n\nIt's possible to view all activity for a specific user. It will display all notes that either created directly by the user or created as a result of that users' actions. Available from the dropdown menu on the Stream panel on the User's detail view. As of v8.2.\n\n## Notifications\n\nA user receives notifications about new stream entries in followed records.\n\n## Posts\n\nYou can create a post related to a certain record. You are also able to attach multiple files and images to a post. Images can be pasted from the clipboard.\n\n### Mentions\n\nIf you want to mention somebody in your post, you need to type `@` symbol and start typing the user's name. The user you have mentioned in your post will be notified.\n\n!!! note\n\n    The user who was mentioned in the post needs to have access to the Stream of the record where they were mentioned. Otherwise, the user won't receive a notification about the post.\n\n!!! note\n\n    The user needs to have a proper *Mention Permission* (set in Roles) to be able to mention a specific user. If the assignment permission is set to `no`, then the user won't be able to mention anyone. If set to `team`, then they will be able to mention only users of their teams. If set to `all`, then they will be able to mention anyone. Portal users are not able to mention users.\n\n### Attachments\n\nUsers can attach files stream posts.\n\nAn administrator can configure the *Attachments* field at Administration > Entity Manager > Note > Fields > attachments (as of v7.2). The following parameters are available:\n\n* Source list – by adding Documents, it enables the ability to attach Documents to stream posts directly;\n* Max file size;\n* Accept – which file types to accept.\n\n### Quote reply\n\n*As of v9.0.*\n\nBy clicking 'Quote Reply' on a stream post, it will paste quoted contents into the text field. If a part of a post is selected, only the selected part will be quoted.\n\n### Reactions\n\n*As of v9.0.*\n\nUsers can add to reactions to stream posts. A user can add only one reaction to a particular post. The author of a post is notified about a reaction. Users can view who reacted to a particular post.\n\nA user can disable notifications about reactions in preferences. If the preferences parameter *Notifications about reactions for non-followed records* is not enabled, the user won't be notified about reactions to their posts in records they do not follow.\n\nAn administrator can define which reactions are available in the system. By default, only Like is available. They can disable reactions by leaving the parameter empty.\n\n## Posts to users\n\nUsers can create posts to certain Users, to certain Teams, to all Users and to self. Access for this feature is controlled by the *Message Permission* in Roles.\n\nYou can post to Users:\n\n* from the *Stream* dashlet;\n* in the *Stream* panel on the user's detail view.\n\n## Filtering\n\nYou can filter what to show in the Stream: *All*, *Posts* or *Updates*. Filters are available in the dropdown in to top-right corner of the panel.\n\n## Global Stream\n\n*As of v8.2.*\n\nThe Global Stream is available on a separate page where users can see all Stream notes, not only related to records they follow. Users can perform search: by specific fields or by a text filter. Notes that user don't have access to are not listed.\n\nThe Global Stream can be useful when you need to search for a specific post. The full-text search is applied when using the text filter.  \n\nAccess to the Global Stream is controlled by Roles.\n\nThe separate navbar Global Stream tab is available. It can be also reached from the Stream page.\n\n!!! note\n\n    If a user does not have *all* access level for all entity types, there are possible scenarios leading to an empty or not complete result list being displayed. It's a server load optimization measure when it would take too much of resources to find the first records the user has access to. Consider adding some search filters in such cases.\n\n## See also\n\n* [Stream quick tour](https://app.supademo.com/demo/cmkvg6g2n2z4p12hh6xvxp6nf)\n* [Activity Stream – Keep up with changes](https://www.espocrm.com/tips/activity-stream/)\n* [Following records in EspoCRM](https://www.espocrm.com/tips/follow-records/)\n"
  },
  {
    "path": "docs/user-guide/text-search.md",
    "content": "# Text Search\n\nIn this article:\n\n* [List view text search](#list-view-text-search)\n* [Global search](#global-search)\n* [Full-text search](#full-text-search)\n\nSee also:\n\n* [Search types in EspoCRM: What you should know](https://www.espocrm.com/tips/search-types/)\n\n## List view text search\n\nOn the record list view, it's possible to perform text search.\n\nThe field list which is used in filtering can be configured under: Administration > Entity Manager > {Entity Type} > Edit > Text Filter Fields.\n\nIt's possible to use a wildcard `*`.\n\n![Text Search](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/text-search/1.png)\n\nThere is an option to force the system to use the 'contains' operator for Varchar fields by default. Parameter is available under Administration > Settings. Note that it can affect performance.\n\nTo disable previous search suggestions, uncheck the checkbox at Preferences > Misc > Disable text filter storing.\n\n## Global search\n\nThe Global Search performs search in multiple entity types simultaneously.\n\nThe list of entity types used in the Global Search can be configured under Administration > Settings > Global Search Entity List.\n\nThe field list which is used in filtering can be configured under Administration > Entity Manager > {Entity Type} > Edit > Text Filter Fields.\n\n![Global Search](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/text-search/2.png)\n\n## Full-text search\n\nFull-text search provides the ability to perform much faster and comprehensive text search. The full-text is performed at the database level.\n\nThe full-text search can be enabled for a specific entity type under Administration > Entity Manager > {Entity Type} > Edit > Full-text search.\n\nAfter enabling full-text-search, running rebuild is required. If you have many records, it's recommended to run rebuild from CLI: `php rebuild.php`.\n\nIn Global Search, the full-text search is always applied (for entity types with enabled full-text search).\n\nThe full-text search is also applied when you search in the list view. Though it can be skipped for some search queries. Yet, it's possible to force a full-text usage by prepending `ft:` to your search query.\n\nThe following operators are available:\n\n* `+` – A leading plus sign indicates that this word must be present.\n* `-` – A leading minus sign indicates that this word must not be present.\n* *no operator* – The word is optional, but the rows that contain it are rated higher.\n* `*` – The truncation (or wildcard) operator. Appended to the word to be affected.\n* `\"` – A phrase enclosed within double quotes must be contained literally, as it was typed.\n\n### Minimum word length\n\nThe MySQL option `ft_min_word_len` defines a minimum word length available for full-text search. By default, it's set to `4`. You might want to set it to `3` to be able to search shorter words.\n\nIf you change this parameter in MySQL, you also need to run rebuild in Espo.\n\n### Stopwords\n\n[MySQL](https://dev.mysql.com/doc/refman/8.0/en/fulltext-stopwords.html) and [MariaDB](https://mariadb.com/docs/server/ha-and-performance/optimization-and-tuning/optimization-and-indexes/full-text-indexes/full-text-index-stopwords) have the list of stopwords that are ignored by full-text search.\n\n### Autocomplete\n\nWhen Full-text search is enabled, autocomplete in link fields may not show suggestions until you type a full word. To have suggestions work for word parts, you can enable the parameter that will append the wildcard operator automatically for autocompletion queries. Administration > Settings > Append wildcard in quick search.\n"
  },
  {
    "path": "docs/user-guide/working-time-calendar.md",
    "content": "# Working Time Calendar\n\n*As of v7.3.*\n\nThe Working Time feature allows you to define working and non-working days for users, teams, and the entire organization. It provides a weekly schedule with customizable hours per weekday, supports exceptions for special working days (such as weekends or days with adjusted hours), and allows marking holidays or leaves.\n\nFeatures:\n\n* Week schedule (weekdays can have different schedule);\n* Working day exceptions (e.g. working weekends, days with a non-standard schedule);\n* Non-working day exceptions (leaves, holidays, etc.).\n\nAdmin users and regular users who have access to the Working Time Calendar scope can manage Working Time Calendars.\n\nWorking Time Calendars can be accessed under:\n\n* Calendar page > top-right dropdown menu > Working Time Calendars;\n* Administration > Working Time Calendars (in the Data panel).\n\nA working Time Calendar record can be:\n\n* Selected as a system default (Administration > System > Working Time Calendar);\n* Selected for a team – will apply to users who have that team set in the *Default Team*;\n* Selected for a specific user.\n\nA Working Time Calendar record defines:\n\n* Time zone;\n* Workday schedule (working time ranges);\n* Week schedule (what weekdays are working, every weekday can have a different schedule).\n\nA Working Time Exception record applies custom working time for a specific day range for specific users or for a whole calendar. It can define non-working days or working days with a custom time schedule.\n\n!!! note\n\n    In Exceptions, the Date End is inclusive.\n\nExamples:\n\n* Holidays for a whole team. Create an Exception record related to the Working Time Calendar with the type *Non-working*.\n* A leave for a specific user (employee). Create an Exception record related to the User (through the *Users* field) with the type *Non-working*.\n* A working Saturday. Create a one-day Exception with the type *Working*.\n* A working day with a shortened time schedule. Create a one-day Exception with the type *Working*, with a custom *Schedule*.\n\nNon-working days have a different background color on the Calendar:\n\n![Calendar](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/working-time-calendar/1.png)\n\nNon-working timeslots:\n\n![Calendar agenda](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/working-time-calendar/2.png)\n\nThe Timeline displays non-working ranges with a different background color:\n\n![Timeline](https://raw.githubusercontent.com/espocrm/documentation/master/docs/_static/images/user-guide/working-time-calendar/3.png)\n\n## Formula functions\n\nThe following formula functions are available.\n\n* `ext\\workingTime\\addWorkingDays(DATE, DAYS)` – adds working days, the result will be a date-time pointing at the beginning of the day  (`00:00`) in a corresponding time zone;\n* `ext\\workingTime\\findClosestWorkingTime(DATE)` – finds the beginning of the next closest working time slot;\n* `ext\\workingTime\\getSummedWorkingHours(FROM, TO)` – get a total number of working hours between two dates;\n* `ext\\workingTime\\getWorkingDays(FROM, TO)` – get a number of working days between two dates;\n* `ext\\workingTime\\hasWorkingTime(FROM, TO)` – whether a date range contains any working time;\n* `ext\\workingTime\\isWorkingDay(DATE_OR_DATETIME)` – whether a date falls into a working day.\n\nFunctions can be applied for the default calendar, user calendar, or team calendar. An entity type ( `'User'` or `'Team'`) and an entity ID can be passed to all workingTime functions as the last two arguments. For example, `ext\\workingTime\\isWorkingDay(dateStart', 'User', assignedUserId)`.\n\n## See also\n\n* [Quick tour](https://app.supademo.com/demo/cmj9rq2v70sm3f6zpxmxq1npw)\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: EspoCRM Documentation\n\nrepo_url: https://github.com/espocrm/documentation/\nedit_uri: edit/master/docs/\n\nextra_javascript: [js/extra.js]\n\nextra_css:\n    - css/extra.css\n\nmarkdown_extensions:\n  - admonition\n  - pymdownx.details\n  - pymdownx.superfences\n  - mdx_truly_sane_lists\n  - attr_list\n  - codehilite:\n      guess_lang: false\n      use_pygments: true\n  - toc:\n      permalink: true\n      toc_depth: 3\n\ntheme:\n    name: material\n    highlightjs: true\n    features:\n        - content.action.edit\n    icon:\n        edit: material/pencil\n    palette:\n        - scheme: default\n          media: \"(prefers-color-scheme: light)\"\n          primary: white\n          accent: white\n          toggle:\n              icon: material/brightness-7\n              name: Switch to dark mode\n        - scheme: slate\n          media: \"(prefers-color-scheme: dark)\"\n          primary: indigo\n          accent: indigo\n          toggle:\n              icon: material/brightness-4\n              name: Switch to light mode\n\n\nnav:\n    - 'Home': 'index.md'\n    - 'Administration':\n        - 'Server configuration':\n            - 'Configuration': 'administration/server-configuration.md'\n            - 'Apache': 'administration/apache-server-configuration.md'\n            - 'Nginx': 'administration/nginx-server-configuration.md'\n            - 'IIS': 'administration/iis-server-configuration.md'\n        - 'System':\n            - 'Installation':\n                - 'Installation': 'administration/installation.md'\n                - 'Installation by script': 'administration/installation-by-script.md'\n                - 'Installation with Docker': 'administration/docker/installation.md'\n                - 'Installation with Traefik': 'administration/docker/traefik.md'\n                - 'Installation with Caddy': 'administration/docker/caddy.md'\n            - 'Upgrading': 'administration/upgrading.md'\n            - 'Extensions': 'administration/extensions.md'            \n            - 'Jobs': 'administration/jobs.md'\n            - 'Config parameters': 'administration/config-params.md'\n            - 'Log': 'administration/log.md'\n            - 'Console commands': 'administration/commands.md'            \n            - 'WebSocket': 'administration/websocket.md'            \n        - 'Essentials':\n            - 'Terms & naming': 'administration/terms-and-naming.md'\n            - 'Troubleshooting': 'administration/troubleshooting.md'\n            - 'Backup and restore': 'administration/backup-and-restore.md'\n            - 'Performance tweaking': 'administration/performance-tweaking.md'\n            - 'Moving to another server': 'administration/moving-to-another-server.md'\n            - 'Security': 'administration/security.md'\n        - 'Customization':\n            - 'Entity Manager': 'administration/entity-manager.md'\n            - 'Fields': 'administration/fields.md'\n            - 'Layouts': 'administration/layout-manager.md'\n            - 'Dynamic Logic': 'administration/dynamic-logic.md'\n            - 'API Before-Save script': 'administration/api-before-save-script.md'\n        - 'Users': 'administration/users-management.md'\n        - 'Roles': 'administration/roles-management.md'\n        - 'Email administration': 'administration/emails.md'\n        - 'Formula':\n            - 'Formula script': 'administration/formula.md'\n            - 'Functions': 'administration/formula-functions.md'\n            - 'Function reference':\n              - 'general': 'administration/formula/general.md'\n              - 'string': 'administration/formula/string.md'\n              - 'datetime': 'administration/formula/datetime.md'\n              - 'number': 'administration/formula/number.md'\n              - 'entity': 'administration/formula/entity.md'\n              - 'record': 'administration/formula/record.md'\n              - 'env': 'administration/formula/env.md'\n              - 'password': 'administration/formula/password.md'\n              - 'array': 'administration/formula/array.md'\n              - 'object': 'administration/formula/object.md'\n              - 'language': 'administration/formula/language.md'\n              - 'json': 'administration/formula/json.md'\n              - 'ext': 'administration/formula/ext.md'\n              - 'util': 'administration/formula/util.md'\n              - 'log': 'administration/formula/log.md'\n              - 'exception': 'administration/formula/exception.md'\n        - 'Import': 'administration/import.md'\n        - 'Portal': 'administration/portal.md'\n        - 'Web-to-Lead': 'administration/web-to-lead.md'\n        - 'Currency': 'administration/currency.md'\n        - 'Dashboards': 'administration/dashboards.md'\n        - 'Authentication':\n            - '2-factor authentication': 'administration/2fa.md'\n            - 'OpenID Connect': 'administration/oidc.md'\n            - 'LDAP':\n                - 'Authorization': 'administration/ldap-authorization.md'\n                - 'Active Directory': 'administration/ldap-authorization-for-ad.md'\n                - 'OpenLDAP': 'administration/ldap-authorization-for-openldap.md'\n        - 'Miscellaneous':\n            - 'Webhooks': 'administration/webhooks.md'\n            - 'Passwords': 'administration/passwords.md'\n            - 'Phone numbers': 'administration/phone-numbers.md'\n            - 'Addresses': 'administration/addresses.md'\n            - 'Maps': 'administration/maps.md'\n            - 'B2C mode': 'administration/b2c.md'\n            - 'Collaborators': 'administration/collaborators.md'\n            - 'Multiple assigned users': 'administration/multiple-assigned-users.md'\n            - 'File storage': 'administration/file-storage.md'\n            - 'SMS sending': 'administration/sms-sending.md'\n            - 'App secrets': 'administration/app-secrets.md'\n    - 'User Guide':\n        - 'Emails':\n            - 'General guidelines': 'user-guide/emails.md'\n            - 'IMAP & SMTP configuration': 'user-guide/imap-smtp-configuration.md'\n            - 'Mass email': 'user-guide/mass-email.md'\n        - 'Stream': 'user-guide/stream.md'\n        - 'Sales management': 'user-guide/sales-management.md'\n        - 'Case management': 'user-guide/case-management.md'\n        - 'Activities & calendar': 'user-guide/activities-and-calendar.md'\n        - 'Campaigns': 'user-guide/campaigns.md'\n        - 'Mail merge': 'user-guide/mail-merge.md'\n        - 'Knowledge base': 'user-guide/knowledge-base.md'\n        - 'Documents': 'user-guide/documents.md'\n        - 'Export': 'user-guide/export.md'\n        - 'Text search': 'user-guide/text-search.md'\n        - 'Working time calendar': 'user-guide/working-time-calendar.md'\n        - 'Printing to PDF': 'user-guide/printing-to-pdf.md'\n        - 'Miscellaneous':\n            - 'Shortcut keys': 'user-guide/shortcuts.md'\n            - 'Markdown syntax': 'user-guide/markdown.md'\n            - 'Browser support': 'user-guide/browser-support.md'\n            - 'Data privacy': 'user-guide/data-privacy.md'\n            - 'Complex expressions': 'user-guide/complex-expressions.md'\n            - 'Optimistic concurrency control': 'user-guide/optimistic-concurrency-control.md'\n    - 'Extensions':\n        - 'Advanced Pack':\n            - 'Overview': 'extensions/advanced-pack/overview.md'\n            - 'Reports': 'user-guide/reports.md'\n            - 'Workflows': 'administration/workflows.md'\n            - 'BPM':\n              - 'Overview': 'administration/bpm.md'\n              - 'Gateways': 'administration/bpm-gateways.md'\n              - 'Events': 'administration/bpm-events.md'\n              - 'Activities': 'administration/bpm-activities.md'\n              - 'Miscellaneous':\n                - 'Examples': 'administration/bpm-examples.md'\n                - 'Signals': 'administration/bpm-signals.md'\n                - 'Compensation': 'administration/bpm-compensation.md'\n                - 'Formula functions': 'administration/bpm-formula.md'\n                - 'Drip email campaign': 'administration/bpm-drip-email-campaign.md'\n                - 'Tracking URLs': 'administration/bpm-tracking-urls.md'\n                - 'Tips': 'administration/bpm-tips.md'\n                - 'Configuration': 'administration/bpm-configuration.md'\n        - 'Sales Pack':\n            - 'Overview': 'extensions/sales-pack/overview.md'\n            - 'Products': 'user-guide/products.md'\n            - 'Prices': 'extensions/sales-pack/prices.md'\n            - 'Sales':\n              - 'Quotes': 'user-guide/quotes.md'\n              - 'Sales orders': 'user-guide/sales-orders.md'\n              - 'Invoices': 'user-guide/invoices.md'\n              - 'Credit notes': 'extensions/sales-pack/credit-notes.md'\n              - 'Delivery orders': 'extensions/sales-pack/delivery-orders.md'\n              - 'Return orders': 'extensions/sales-pack/return-orders.md'\n              - 'Write-offs': 'extensions/sales-pack/write-offs.md'\n              - 'Subscriptions': 'extensions/sales-pack/subscriptions.md'\n            - 'Purchases':\n              - 'Suppliers': 'extensions/sales-pack/suppliers.md'\n              - 'Purchase orders': 'extensions/sales-pack/purchase-orders.md'\n              - 'Receipt orders': 'extensions/sales-pack/receipt-orders.md'\n              - 'Bills': 'extensions/sales-pack/bills.md'\n              - 'Bill credits': 'extensions/sales-pack/bill-credits.md'\n            - 'Inventory management': 'extensions/sales-pack/inventory-management.md'\n            - 'Payments': 'extensions/sales-pack/payments.md'\n            - 'Taxes': 'extensions/sales-pack/taxes.md'\n            - 'Tax codes': 'extensions/sales-pack/tax-codes.md'\n            - 'Issuance locking': 'extensions/sales-pack/issuance-locking.md'\n            - 'Multi-currency': 'extensions/sales-pack/multi-currency.md'\n            - 'Reports': 'extensions/sales-pack/reports.md'\n        - 'Project Management':\n            - 'Projects': 'extensions/project-management/projects.md'\n        - 'Meeting Scheduler':\n            - 'Meeting Scheduler': 'extensions/meeting-scheduler/index.md'\n        - 'Google Integration':\n            - 'Setting-up': 'extensions/google-integration/setting-up.md'\n            - 'Calendar': 'extensions/google-integration/calendar.md'\n            - 'Contacts': 'extensions/google-integration/contacts.md'\n            - 'Gmail': 'extensions/google-integration/gmail.md'\n        - 'Outlook Integration':\n            - 'Setting-up': 'extensions/outlook-integration/setting-up.md'\n            - 'Calendar': 'extensions/outlook-integration/calendar.md'\n            - 'Contacts': 'extensions/outlook-integration/contacts.md'\n            - 'Email': 'extensions/outlook-integration/email.md'\n        - 'VoIP Integration':\n            - 'Overview': 'extensions/voip-integration/overview.md'\n            - '3CX PBX': 'extensions/voip-integration/3cx-integration-setup.md'\n            - 'Asterisk server': 'extensions/voip-integration/asterisk-integration-setup.md'\n            - 'Twilio service' : 'extensions/voip-integration/twilio-integration-setup.md'\n            - 'Starface server': 'extensions/voip-integration/starface-integration-setup.md'\n            - 'Binotel service' : 'extensions/voip-integration/binotel-integration-setup.md'\n            - 'IexPBX server' : 'extensions/voip-integration/iexpbx-integration-setup.md'\n            - 'Docker container': 'extensions/voip-integration/docker-container.md'\n            - 'Customization': 'extensions/voip-integration/customization.md'\n            - 'Troubleshooting' : 'extensions/voip-integration/troubleshooting.md'\n        - 'Zoom Integration':\n            - 'Zoom Integration': 'extensions/zoom-integration/index.md'\n        - 'Stripe Integration':\n            - 'Stripe Integration': 'extensions/stripe-integration/index.md'\n        - 'Export Import':\n            - 'Overview': 'extensions/export-import/overview.md'\n            - 'Export': 'extensions/export-import/export.md'\n            - 'Import': 'extensions/export-import/import.md'\n            - 'Compare': 'extensions/export-import/compare.md'\n            - 'Run by code': 'extensions/export-import/run-by-code.md'\n            - 'Customization': 'extensions/export-import/customization.md'\n    - 'Developer':\n        - 'Index': 'development/index.md'\n        - 'Getting started': 'development/how-to-start.md'\n        - 'Making extension package': 'development/extension-packages.md'\n        - 'Modules': 'development/modules.md'\n        - 'Tests': 'development/tests.md'\n        - 'Translation': 'development/translation.md'\n        - 'Coding rules': 'development/coding-rules.md'\n        - 'Backend':\n          - 'Dependency injection': 'development/di.md'\n          - 'Metadata': 'development/metadata.md'\n          - 'Metadata reference':\n            - 'scopes': 'development/metadata/scopes.md'\n            - 'entityDefs': 'development/metadata/entity-defs.md'\n            - 'aclDefs': 'development/metadata/acl-defs.md'\n            - 'selectDefs': 'development/metadata/select-defs.md'\n            - 'recordDefs': 'development/metadata/record-defs.md'\n            - 'clientDefs': 'development/metadata/client-defs.md'\n            - 'entityAcl': 'development/metadata/entity-acl.md'\n            - 'pdfDefs': 'development/metadata/pdf-defs.md'\n            - 'logicDefs': 'development/metadata/logic-defs.md'\n            - 'notificationDefs': 'development/metadata/notification-defs.md'\n            - 'streamDefs': 'development/metadata/stream-defs.md'\n            - 'fields': 'development/metadata/fields.md'\n            - 'dashlets': 'development/metadata/dashlets.md'\n            - 'authenticationMethods': 'development/metadata/authentication-methods.md'\n            - 'integrations': 'development/metadata/integrations.md'\n            - 'app':\n              - 'acl': 'development/metadata/app-acl.md'\n              - 'acl-portal': 'development/metadata/app-acl-portal.md'\n              - 'actions': 'development/metadata/app-actions.md'\n              - 'address-formats': 'development/metadata/app-address-formats.md'\n              - 'admin-panel': 'development/metadata/app-admin-panel.md'\n              - 'api': 'development/metadata/app-api.md'\n              - 'app-params': 'development/metadata/app-app-params.md'\n              - 'authentication': 'development/metadata/app-authentication.md'\n              - 'authentication2FAMethods': 'development/metadata/app-authentication-2fa-methods.md'\n              - 'cleanup': 'development/metadata/app-cleanup.md'\n              - 'client': 'development/metadata/app-client.md'\n              - 'clientNavbar': 'development/metadata/app-client-navbar.md'\n              - 'clientIcons': 'development/metadata/app-client-icons.md'\n              - 'clientRecord': 'development/metadata/app-client-record.md'\n              - 'clientRoutes': 'development/metadata/app-client-routes.md'\n              - 'complexExpression': 'development/metadata/app-complex-expression.md'\n              - 'config': 'development/metadata/app-config.md'\n              - 'consoleCommands': 'development/metadata/app-console-commands.md'\n              - 'containerServices': 'development/metadata/app-container-services.md'\n              - 'currency': 'development/metadata/app-currency.md'\n              - 'currencyConversion': 'development/metadata/app-currency-conversion.md'\n              - 'databasePlatforms': 'development/metadata/app-database-platforms.md'\n              - 'dateTime': 'development/metadata/app-date-time.md'\n              - 'defaultDashboardLayouts': 'development/metadata/app-default-dashboard-layouts.md'\n              - 'defaultDashboardOptions': 'development/metadata/app-default-dashboard-options.md'\n              - 'emailTemplate': 'development/metadata/app-email-template.md'\n              - 'entityManager': 'development/metadata/app-entity-manager.md'\n              - 'entityManagerParams': 'development/metadata/app-entity-manager-params.md'\n              - 'entityTemplateList': 'development/metadata/app-entity-template-list.md'\n              - 'entityTemplates': 'development/metadata/app-entity-templates.md'\n              - 'export': 'development/metadata/app-export.md'\n              - 'fieldProcessing': 'development/metadata/app-field-processing.md'\n              - 'file': 'development/metadata/app-file.md'\n              - 'fileStorage': 'development/metadata/app-file-storage.md'\n              - 'formula': 'development/metadata/app-formula.md'\n              - 'hook': 'development/metadata/app-hook.md'\n              - 'image': 'development/metadata/app-image.md'\n              - 'jsLibs': 'development/metadata/app-js-libs.md'\n              - 'language': 'development/metadata/app-language.md'\n              - 'layouts': 'development/metadata/app-layouts.md'\n              - 'linkManager': 'development/metadata/app-link-manager.md'\n              - 'mapProviders': 'development/metadata/app-map-providers.md'\n              - 'massActions': 'development/metadata/app-mass-actions.md'\n              - 'metadata': 'development/metadata/app-metadata.md'\n              - 'orm': 'development/metadata/app-orm.md'\n              - 'pdfEngines': 'development/metadata/app-pdf-engines.md'\n              - 'popupNotifications': 'development/metadata/app-popup-notifications.md'\n              - 'portalContainerServices': 'development/metadata/app-portal-container-services.md'\n              - 'reactions': 'development/metadata/app-reactions.md'\n              - 'rebuild': 'development/metadata/app-rebuild.md'\n              - 'record': 'development/metadata/app-record.md'\n              - 'recordId': 'development/metadata/app-record-id.md'\n              - 'regExpPatterns': 'development/metadata/app-reg-exp-patterns.md'\n              - 'relationships': 'development/metadata/app-relationships.md'\n              - 'scheduledJobs': 'development/metadata/app-scheduled-jobs.md'\n              - 'select': 'development/metadata/app-select.md'\n              - 'smsProviders': 'development/metadata/app-sms-providers.md'\n              - 'templateHelpers': 'development/metadata/app-template-helpers.md'\n              - 'templates': 'development/metadata/app-templates.md'\n              - 'webSocket': 'development/metadata/app-web-socket.md'\n          - 'ORM': 'development/orm.md'\n          - 'Select Builder': 'development/select-builder.md'\n          - 'API actions': 'development/api-action.md'\n          - 'Services': 'development/services.md'\n          - 'Hooks': 'development/hooks.md'\n          - 'ACL': 'development/acl.md'\n          - 'Entry points': 'development/entry-points.md'\n          - 'Miscellaneous':\n              - 'Coding practices': 'development/coding-practices.md'\n              - 'Autoload': 'development/autoload.md'\n              - 'Entity type': 'development/custom-entity-type.md'\n              - 'Container services': 'development/container-services.md'\n              - 'Template helpers (PDF)': 'development/template-custom-helper.md'\n              - 'Formula functions': 'development/new-function-in-formula.md'\n              - 'Scheduled jobs': 'development/scheduled-job.md'\n              - 'Duplicate checking': 'development/duplicate-check.md'\n              - 'Database indexes': 'development/db-indexes.md'\n              - 'App params': 'development/app-params.md'\n              - 'Jobs': 'development/jobs.md'\n              - 'Email sending': 'development/email-sending.md'\n              - 'Calculated fields': 'development/calculated-fields.md'\n              - 'Config parameters': 'development/custom-config-parameters.md'\n              - 'Value Objects': 'development/orm-value-objects.md'\n              - 'Attachments': 'development/attachments.md'\n        - 'Frontend':\n          - 'View': 'development/view.md'\n          - 'Templates': 'development/frontend/templates.md'\n          - 'Model': 'development/model.md'\n          - 'Collection': 'development/collection.md'\n          - 'HTML & CSS': 'development/frontend/html-css.md'\n          - 'Ajax requests': 'development/frontend/ajax.md'\n          - 'Controller & routing': 'development/frontend/controller.md'\n          - 'Dependency injection': 'development/frontend/dependency-injection.md'\n          - 'Modal dialogs': 'development/modal.md'\n          - 'Confirmation dialogs': 'development/confirm-dialog.md'\n          - 'Custom views': 'development/custom-views.md'\n          - 'View setup handlers': 'development/frontend/view-setup-handlers.md'\n          - 'Save error handlers': 'development/frontend/save-error-handlers.md'\n          - 'Dynamic handler': 'development/dynamic-handler.md'\n          - 'Fields':\n              - 'Custom field type': 'development/custom-field-type.md'\n              - 'Customizing existing fields': 'development/customize-standard-fields.md'\n          - 'Miscellaneous':\n              - 'Buttons & actions on record views': 'development/custom-buttons.md'\n              - 'Panels on record view': 'development/frontend/record-panels.md'\n              - 'Custom CSS file': 'development/custom-css.md'\n              - 'Dashlets': 'development/how-to-create-a-dashlet.md'\n              - 'Link-multiple field with primary record': 'development/link-multiple-with-primary.md'\n              - 'Monkey patching': 'development/frontend/monkey-patching.md'\n              - 'Campaigns':\n                -  'Custom unsubscribe page': 'development/campaign-unsubscribe-template.md'\n        - 'API':\n          - 'API overview': 'development/api.md'\n          - 'Endpoints':\n            - 'CRUD operations': 'development/api/crud.md'\n            - 'Related records': 'development/api/relationships.md'\n            - 'Stream': 'development/api/stream.md'\n            - 'CurrencyRate': 'development/api/currency-rate.md'\n            - 'Attachment': 'development/api/attachment.md'\n            - 'I18n': 'development/api/i18n.md'\n            - 'Metadata': 'development/api/metadata.md'\n            - 'Account': 'development/api/account.md'\n          - 'Misc':\n            - 'Search parameters': 'development/api-search-params.md'\n            - 'Usage tutorial': 'development/api-tutorial.md'\n          - 'Clients':\n            - 'PHP': 'development/api-client-php.md'\n            - 'JavaScript': 'development/api-client-js.md'\n            - 'Python': 'development/api-client-python.md'\n            - 'Rust': 'development/api-client-rust.md'\n            - 'Java': 'development/api-client-java.md'\n            - 'Go': 'development/api-client-go.md'\n            - 'Zig': 'development/api-client-zig.md'\n"
  }
]