Development Toolkit

Manifest

An add-on manifest is used to describe how your CAKE.com Marketplace add-on integrates with the Clockify app. Your add-on can contain some additional UI elements that will be added by installing that add-on and manifest file can define details regarding those elements.
Manifest is a JSON file that needs to be hosted on a path to an add-on URL app and included in the add-on URL root folder.

When creating an add-on at CAKE.com Marketplace, manifest URL is required. You need to enter it in a form at the first step of creating an add-on

Top-level properties

PropertyRequiredDescription
schemaVersionnoVersion of Clockify JSON manifest scheme according to which manifest is validated. Multiple versions are supported, version: “1.0”, “1.0.1”, “1.0.2”, “1.1”, “1.2” and current version: “1.3”.
If not defined, last version is used.
keyyesUnique key chosen by developer, can’t be changed (2-50 characters)
nameyesSame as the one submitted for review (1-50 characters)
baseUrlyesURL of an add-on
descriptionnoBrief description of add-on
iconPathnoPath to add-on hosted image which will serve as an add-on icon. Path is part of the URL from which the image will be served. Full URL is constructed by concatenating add-on ‘baseUrl’ and path.
lifecyclenoList of defined lifecycle hooks defined for a specific add-on.

Possible values: INSTALLED, SETTINGS-UPDATED, SETTINGS-CHANGED and DELETED
webhooksnoContain details about events that trigger the webhook requests
componentsnoSpecified UI components
settingsno*Can be additional settings for UI elements organized by nesting tabs and Group, or URL path

Possible values: TXT, NUMBER, DROPDOWN_SINGLE, DROPDOWN_MULTIPLE, CHECKBOX, LINK

Possible value for URL path: e.g. settings: “/settings”
Note: When updating the value, change ID or type, e.g. URL in the settings can’t be changed with an update unless you change type or ID of the settings.

*Required if defined
minimalSubscriptionPlanyesMinimal Clockify’s subscription plan that is required for add-on. This plan is used when checking if user’s current plan is at least equal to the plan required by add-on.

Possible values: FREE, BASIC, STANDARD, PRO, ENTERPRISE
scopesnoList of Clockify’s API scopes that add-on is using. Scope is specified by Clockify’s endpoint group, and READ/WRITE permission where WRITE consists of PUT/POST/DELETE and CREATE endpoints that belong to a certain scope. WRITE permission doesn’t automatically imply READ permission.

Possible values: CLIENT_READ, CLIENT_WRITE, PROJECT_READ, PROJECT_WRITE, TAG_READ, TAG_WRITE, TASK_READ, TASK_WRITE, TIME_ENTRY_READ, TIME_ENTRY_WRITE, EXPENSE_READ, EXPENSE_WRITE, INVOICE_READ, INVOICE_WRITE, USER_READ, USER_WRITE, GROUP_READ, GROUP_WRITE, WORKSPACE_READ, WORKSPACE_WRITE, CUSTOM_FIELDS_READ, CUSTOM_FIELDS_WRITE, APPROVAL_READ, APPROVAL_WRITE, SCHEDULING_READ, SCHEDULING_WRITE, REPORTS_READ, REPORTS_WRITE, TIME_OFF_READ, TIME_OFF_WRITE

Components

Components contain details about your add-ons UI elements such as their type, e.g. tab, widget, sidebar, or permission access level, e.g. component can be accessed by admin or everyone.

PropertyRequiredDescription
typeyesSpecifies which kind of component will be rendered. If component is ‘tab’, it also comes with the name of Clockify page where ‘tab’ component will be rendered. Add-on cannot define two components of the same type e.g. no two components of “sidebar” type.

Possible values: sidebar, widget, timeoff.tab, schedule.tab, approvals.tab, reports.tab, activity.tab, team.tab, projects.tab
optionsnoHere you can define some component-specific options for a component that holds add-on app.
labelyesCustom label for component. For example, if component is ‘tab’, value of ‘label’ property will be displayed in UI.
pathyesDefines an add-on server path that will display an iFrame content in a component. Path is part of the URL from which a component content will be served. Full URL is constructed by concatenating add-on ‘baseUrl’ and path.

Possible values: /sidebar
iconPathnoPath to add-on hosted image which will serve as an icon for a Clockify component. Path is part of the URL from which the image will be served. Full URL is constructed by concatenating add-on ‘baseUrl’ and path.
accessLevelyesSpecifies who can access add-on component. You can either choose to give access only to Clockify workspace admins, or everyone.

Possible values: ADMINS, EVERYONE
widthnoSpecifies the width of a widget.

Possible value: integer
heightnoSpecifies the height of a widget.

Possible value: integer

Example

"components": [
    {
    "type": "sidebar",
    "label": "${sidebarLabel}",
    "accessLevel": "ADMINS",
    "path": "${sidebarPath}",
    "options": {
        "option 1": "option 1 value",
        "option 2": "option 2 value"
    },
    "iconPath": "/trt"
  ]

Lifecycles

Lifecycles contain events add-on receives when installed, deleted, or when its settings are updated.

PropertyRequiredDescription
pathyesPath to add-on endpoint designated for receiving lifecycle hooks from the Clockify side. Path is a part of URL to which a lifecycle hook will be sent. A full URL is constructed by concatenating add-on ‘baseUrl’ and path.
typeyesSpecifies and add-on lifecycle event you want to be notified by Clockify.
Possible values: INSTALLED, SETTINGS_UPDATED, STATUS_CHANGED, DELETED

Example

"lifecycle": [
    {
      "path": "/postinstall",
      "type": "INSTALLED"
    },
    {
      "path": "/uninstalled",
      "type": "DELETED"
    }
  ]

Webhooks

Webhooks contain details about events that trigger the webhook requests. There can be various types of webhooks, depending on the events.

PropertyRequiredDescription
pathyesPath to add-on endpoint designated for receiving webhooks from the Clockify side. Path is just part of URL to which the webhook will be sent. Full URL is constructed by concatenating add-on ‘baseUrl’ and path.

e.g. /clockify/webhooks
eventyesClockify event that triggers webhook is sent to a specified URL. This URL is constructed by concatenating add-on ‘baseUrl’ and ‘webhook.path’.

Possible values:
NEW_PROJECT, PROJECT_UPDATED, PROJECT_DELETED, NEW_TASK, TASK_UPDATED, TASK_DELETED, NEW_CLIENT, CLIENT_UPDATED, CLIENT_DELETED, NEW_TAG, TAG_UPDATED, TAG_DELETED, NEW_TIMER_STARTED, TIMER_STOPPED, TIME_ENTRY_UPDATED, TIME_ENTRY_DELETED, NEW_TIME_ENTRY, NEW_INVOICE, INVOICE_UPDATED, USER_JOINED_WORKSPACE, USER_DELETED_FROM_WORKSPACE, USER_DEACTIVATED_ON_WORKSPACE, USER_ACTIVATED_ON_WORKSPACE, USER_EMAIL_CHANGED, USER_UPDATED, NEW_APPROVAL_REQUEST, APPROVAL_REQUEST_STATUS_UPDATED, TIME_OFF_REQUESTED, TIME_OFF_REQUEST_APPROVED, TIME_OFF_REQUEST_REJECTED, TIME_OFF_REQUEST_WITHDRAWN, BALANCE_UPDATED, USER_GROUP_CREATED, USER_GROUP_UPDATED, USER_GROUP_DELETED, EXPENSE_CREATED, EXPENSE_UPDATED, EXPENSE_DELETED, ASSIGNMENT_CREATED, ASSIGNMENT_UPDATED, ASSIGNMENT_DELETED, ASSIGNMENT_PUBLISHED

Example

"webhooks": [
    {
      "event": "NEW_TIME_ENTRY",
      "path": "/clockify/time-entry"
    },
    {
      "event": "NEW_CLIENT",
      "path": "clockify/client"
    }
  ],

Settings

Settings contain details about additional settings for UI elements (e.g. dropdown with options 1, 2, 3). Settings are organized by nesting tabs and groups. Each setting must have id, name, type, value and access level. Value and type of setting must be compatible.
If the value of settings is a URL path (e.g. /settings), settings are taken from an add-on and displayed in Clockify app via iFrame. These types of settings are hosted on an add-on.
If empty, there are no settings for that add-on.

PropertyRequiredDescription
idyesSettings unique identifier
nameyesSettings name
valueyesSpecifies settings’ value. Each value is displayed differently in UI and the value must be compatible with a specified type.

Possible values: string
typeyesSpecifies settings’ value type.

Possible values: TXT
accessLevelyesSpecifies who can access add-on settings. You can either choose to give access only to Clockify workspace admins, or everyone.

Possible values: ADMINS, EVERYONE

Example


"settings": [
    {
        "id": "sidebarLabel",
        "accessLevel": "ADMINS",
        "value": "Custom label",
        "name": "Custom label for component",
        "type": "TXT"
     },
     {
        "id": "sidebarPath",
        "accessLevel": "ADMINS",  
        "value": "/sidebar",
        "name": "Custom label for component",
        "type": "TXT"
      }
 ]

Tabs

Tabs are at the top level of hierarchy when defining settings.
Tabs cannot be nested in other tabs or groups and they need to have at least one type of settings defined, whether it’s a “settings” or a “groups” property. If “groups” property is the one defined, it needs to have at least one “settings” property defined in it.
For more information on “groups”, check out Groups section.

PropertyRequiredDescription
idyesTab identifier

e.g. tab_one
nameyesTab name displayed in UI

e.g. Tab one
headernoBanner with info text shown before all settings and groups contained in tab
settingsno List of settings contained in tab
groupsnoSettings grouped by certain criteria

Example

"settings": {
    "tabs": [
    {
        "id": "Tab id",
        "name": "Tab one title",
        "header": {
            "title": "Title text"
        },
        "groups": [
            {
                "id": "Group id",
                "title": "Group one title",
                "description": "Group description",
                "header": {
                    "title": "Header title"
                },
                "settings": [
                    {
                        "id": "Setting id",
                        "name": "Default setting",
                        "description": "Description of default setting",
                        "placeholder": "Default setting here...",
                        "type": "TXT",
                        "value": "Value of default setting",
                        "required": true,
                        "copyable": true,
                        "readOnly": false, 
                        "accessLevel": "ADMINS"
                    }
                ]
            }
        ],
        "settings": [
            {
                "id": "Tab setting",
                "name": "Tab setting",
                "type": "TXT",
                "value": "Some value",
                "required": true,
                "accessLevel": "EVERYONE"
            }
        ]
    }
]}
]

Groups

Serves as another level of hierarchy when defining settings. Group can be part of tabs, and one tab can contain multiple groups. Each group needs to have its “id” and can have “title”, “description”, “header” and “settings”.

PropertyRequiredDescription
idyesGroup identifier

e.g. “group_one”
titleyesGroup title. Displayed in UI.

e.g. “Group one title”
descriptionnoBrief description of the settings that a given group contains.

e.g. “Group description”
header noBanner with an info text displayed above all the settings that a given group contains.

e.g. Group info text
settingsyesList of settings the group contains

Example

"groups": [
            {
                "id": "Group id",
                "title": "Group one title",
                "description": "Group description",
                "header": {
                    "title": "Header title"
                },
                "settings": [
                    {
                        "id": "Setting id",
                        "name": "Default setting",
                        "description": "Description of default setting",
                        "placeholder": "Default setting here...",
                        "type": "TXT",
                        "value": "Value of default setting",
                        "required": true,
                        "copyable": true,
                        "readOnly": false,
                        "accessLevel": "ADMINS"
                    }
                ]
            }
        ]

Settings

These settings are defined in “settings” or “groups” properties.

PropertyRequiredDescription
idyesSettings unique identifier
nameyesSettings name
descriptionnoBrief description of settings. It states settings’ purpose, affect, etc.
palceholdernoText displayed in UI form field if settings have no value.
typeyesSpecifies settings’ value type. Each type is displayed differently in UI and the value must be compatible with a specified type e.g. if ‘type’ is TXT, ‘value’ must be ‘string’, if ‘type’ is DROPDOWN, ‘value’ must be ‘array’.

Possible value for Group type: TXT / NUMBER / DROPDOWN_SINGLE / DROPDOWN_MULTIPLE / CHECKBOX / LINK
Note: Checkbox is switch. In case settings type is changed in an add-on update, the user selected value will be removed and the default value will be set.
keynoServes as a key for settings that represent a key-value pair e.g. if you have documentation add-on which shows document corresponding to the Clockify page i.e. you need to match the Clockify page to the URL of the document describing how to use that page. In that case, key would be ‘Clockify page’, and ‘value’ would be ‘URL of the document’.
valueyesSettings’ value. It must correspond to the type of settings which is defined in the “type” property
allowedValuesno*Specifies which options will be displayed in dropdown.

* Required if type of settings defined in the “type” property is DROPDOWN_SINGLE or DROPDOWN_MULTIPLE.
requirednoDefines if setting is required for add-on to work

Possible values: true/false
copyablenoDefines if setting value will be displayed with ‘Copy’ button for easier copying.
readOnlynoDefines if setting value is read-only i.e. setting value cannot be updated.
accessLevelyesDefines if settings can be viewed by regular users, or admins only.

Possible values: ADMINS or EVERYONE

Example

"settings": [
    {
        "id": "Setting id",
        "name": "Default setting",
        "description": "Description of default setting",
        "placeholder": "Default setting here...",
        "type": "TXT",
        "value": "Value of default setting",
        "required": true,
        "copyable": true,
        "readOnly": false,
        "accessLevel": "ADMINS"
     }
 ]