Links

Building Connector Actions

We provide our SaaS customers an easy way to manage their own connectors and its actions and endpoints.

Introduction

To create a new Connector Actions you need to understand the basics of API calls and the corresponding terms we use in the Connector Action creation/edit dialog:
Connector Action creation/edit dialog
All Actions are created per Connector and you can add them on the Connector settings (you might need to request access by contacting us) - Actions:
A new page will open with all Actions for this Connector, where you can create new ones or edit existing ones:
Create/Edit rights for Connector Actions are given on a per Connector basis, so you might be able to see some Connector Actions, but cannot edit them.

Fields

As shown above, there are quite a lot of different fields which are part of each Action:
  • ID: The uuid of the Action, this is needed if you want to change the Action via API (read-only)
  • Connector: The Connector the Action belongs to (read-only)
  • Action Name: Name of the Action in snake_case, it will be shown in Title Case in the Flow Builder and _ will be replaced by spaces
    • This is usually equal to the endpoint name in the API documentation
    • However, we recommend to start every Action name with the method and indicating with plural forms, whether the action is about one or multiple records, e.g. get_action (= one action) and get_actions (= multiple actions, often also called list_... in API documentations)
  • Order Rank: The order in which the Action will be shown in the Flow Builder
  • Status: Only Actions with status active are visible to non-admin users
  • Short Description: Description about the Action that will be shown in the tooltip in the Flow Builder. This is
  • Tag: Tag the Action should be grouped by in the Flow Builder
  • Internal Docs: Link to Locoia documentation, which will be shown in the Flow Builder
  • External Docs: Link to external API documentation, which will be shown in the Flow Builder
  • Method: This can only be left empty for 'special' Actions such as webhook trigger actions
  • Endpoint: This will be appended to the base domain of the Connector
    • When starting the endpoint with /, it will overwrite anything that comes after the first / in the base domain. This is often needed if a few Actions are only available in an older API version than the one specified in the base domain
    • When starting the endpoint with https://, the entire base domain will be overwritten and the endpoint will be used instead. This is needed for APIs where a few Actions have completely different base domains than all other Actions of the same Connector
  • UI Form Schema: JSON which will render the input form that is visible in the Flow Builder. More details below
  • Request Body Template: Jinja which will render the request body. More details below
  • Request Header Template: Jinja which will render the request header, which will be used in addition to the Header configured in the Connector. More details below
  • Reporting Flow: Flow used for retrieving data for this Action in a Data Source
  • Pre Save Flow: Flow which creates a webhook (for webhook trigger actions only)
  • On Delete Flow: Flow which deletes a webhook (for webhook trigger actions only)
  • Supports automatic pagination: Whether the action supports automatic pagination. Automatic pagination needs to be configured on the Connector itself in order to work

UI Form Schema

The UI Form Schema
Below is an extensive list of form schema variations:
{
"ui_form_schema": {
"classicinput": {
"required": true,
"title": "input",
"type": "text"
},
"date": {
"title": "date",
"type": "date"
},
"daterange": {
"title": "date A and B",
"type": "daterange"
},
"datetime": {
"required": true,
"title": "date and time",
"type": "datetime"
},
"email": {
"placeholder": "E-mail zum bestätigen",
"title": "Email",
"type": "email"
},
"multiselect": {
"default": [
"normal",
"low"
],
"enum": [
"urgent",
"high",
"normal",
"low"
],
"allowCreate": true,
"multiple": true,
"title": "multi select",
"type": "select"
},
"number": {
"default": 2,
"max": 3,
"min": -1,
"step": 0.25,
"title": "Zahl zwischen -1 und 3",
"type": "number"
},
"password": {
"title": "password",
"type": "password"
},
"singleselect": {
"default": "problem",
"enum": [
"problem",
"incident",
"question",
"task"
],
"title": "single selct",
"type": "select"
},
"switch": {
"default": true,
"title": "Aus/An",
"type": "switch"
},
"textarea": {
"info": "Type some text",
"maxLength": 20,
"minLength": 10,
"placeholder": "Type...",
"required": true,
"rows": 3,
"title": "textarea",
"type": "text"
}
}
}
To allow a user to add manually their own custom options in a select dropdown, add the below to:
"type": "select",
"allowCreate": true

Multiple select (enum)

Screenshot how it looks to the user:
Rendered UI form schema

UI form schema example:

{
"include": {
"title": "Details to include",
"type": "select",
"multiple": true,
"enum": [
"owner",
"creater",
"updater",
"source",
"contacts",
"sales_account",
"deal_stage",
"deal_type",
"deal_reason",
"campaign",
"deal_payment_status",
"deal_product",
"currency",
"probability",
"created_at",
"updated_at"
]
}
}

Request body usage:

{
"include": {{ include | jsonify }}
}

Endpoint (query parameter) usage of multi select:

Example of a multi select in the URL parameters to get a list as a result: [ "owner", "contacts",... ]
{% if include != [] %}&include={{include |replace("[", "")|replace("]", "")|replace("'", "")|replace(" ", "")}}{% endif %}

Action endpoints and building their query strings dynamically

In order to build query strings dynamically (i.e. not having to take care of when to player a ? vs a &) always use & and our backend will dynamically take care of placing the ? correctly by replacing the first occurrence of & with a ? Note: This is only being done if the query string does not include a ?

Custom Fields

In order to allow custom fields where the type may not be known to send data in the right format, the following formats have to be used.

Request Body

I.e. booleans and numbers without quotation marks the following line has to be inserted, instead of "{{item.key}}": "{{item.value}}", when configuring the connector action request body:
{% if custom_fields | length > 0 %},{% endif %}
{% for item in custom_fields %}
"{{ item.key }}": {% if item.type == 'number' %}{{ item.value }}{% elif item.type == 'switch' %}{{ item.value | lower }}{% else %}"{{item.value}}"{% endif %}
{% if not loop.last %},{% endif %}
{% endfor %}

Endpoint

Custom fields can also be used in the endpoint:
{% if custom_fields is defined %}{% for item in custom_fields %}&{{item.key}}={{item.value}}{% endfor %}{% endif %}
The most known use-case for this is for APIs, such as Zendesk or Salesforce, that are popular for using custom fields, added by each user individually.

Code Highlighting for SQL, htmlmixed, jinja2, javascript, python

Add code highlighting by making type `code` and adding the mode type to one of these five sql, htmlmixed, jinja2, javascript, python (letters all lower case). Further syntax highlighting can be added upon request as per: Code Highlighting
{
"myField": {
"type": "code",
"mode": "sql",
"title": "My Title"
}
}

Nested Form Schema

Example image

Example code

{
"clickEvent": {
"title": "Click Event",
"type": "nested_object",
"children": {
"shouldReactOnClick": {
"title": "Click on/off",
"type": "switch",
"info": "Determinte if click on a value on the chart should open a link.",
"default": false
},
"urlTemplate": {
"title": "URL template",
"info": "Base URL with placeholders (use the SQL columns with doubly curly braces).",
"type": "text",
"placeholder": "https://www.google.com/search?q={{category}}"
},
"test": {
"title": "Test",
"info": "test",
"type": "nested_object",
"children": {
"testChild": {
"title": "testChild",
"type": "text"
},
"testChild2": {
"title": "testChild2",
"type": "text"
},
"test": {
"title": "Test",
"info": "test",
"type": "nested_object",
"children": {
"testChild": {
"title": "testChild",
"type": "text"
},
"testChild2": {
"title": "testChild2",
"type": "text"
},
"test": {
"title": "Test",
"info": "test",
"type": "nested_object",
"children": {
"testChild": {
"title": "testChild",
"type": "text"
},
"testChild2": {
"title": "testChild2",
"type": "text"
},
"test": {
"title": "Test",
"info": "test",
"type": "nested_object",
"children": {
"testChild": {
"title": "testChild",
"type": "text"
},
"testChild2": {
"title": "testChild2",
"type": "text"
}
}
}
}
}
}
}
}
}
}
}
}

Sending emails

Often email providers expect content to be send based64 encoded. Please use the Jinja filter base64_encode (or base64_decode) for this like this:
{{ myEmailContent | base64_encode }}

Regular Expression (RegEx) Validation

To validate the user input for the fields, you can make use of RegEx in order to be fully flexible with the validation. To use it, these two fields need to be added to the form schema:
  • pattern - The RegEx pattern (Note : The backslash (\) which is commonly used in RegEx patterns needs to be escaped, so instead of \ two backslashes need to be used: \\)
  • regexErrorMessage - The error message that should be displayed when the input doesn't match the pattern
For example the the FTP Helper' authentication form has a field for the Server URL, which validates the user input:
"server_url": {
"title": "FTP Server URL",
"type": "text",
"required": true,
"placeholder": "ftp://my.server.com:22",
"info": "Start your path with the protocol (ftp/ftps/sftp), followed by the domain of your server and followed by the port.",
"pattern": "/^s{0,1}ftps{0,1}:\\/\\/[\\w-_./]+:\\d+$/",
"regexErrorMessage": "Required formats: ftps://server-domain.com:22 or starting with sftp:// ftp://"
}
Example error message
For a typical connector the pattern looks often similar to the one of the Freshsales connector:
"pattern": "/^https:\\/\\/[\\w-_]+\\.freshsales\\.io\\/api\\/$/"
In order to validate Jinja reference or url input this pattern can be used:
"pattern": "/^({{|{%http).+$/"
If the entire input should match the pattern you need to include /^your_pattern$/.
^ is the start of the line and $ is the end of the line.
You can easily setup and test your RegEx patterns in tools like RegExr.

UUID mappings in select drop downs

E.g. LexOffice has UUIDs for categories like:
Warenverkäufe 8f8664a8-fd86-11e1-a21f-0800200c9a66
This can be solved with the following in the request body template:
{% set categoryMapping = {"Warenverkäufe":"8f8664a8-fd86-11e1-a21f-0800200c9a66", .. }
{
...
"categoryId": "{{ categoryMapping[categoryId] }}"
...
}
Now the UI Form Schema can just have a list (select) with values like Warenverkäufe .

Available variables and Jinja functions

In the actions almost all Jinja variables and functions that are available in Flows are available in the Action's endpoint, request body, and request header as well, except for these:
  • date date_de
  • date_utc
  • date_us
  • date_de_7
  • date_utc_7
  • date_us_7
  • date_de_30
  • date_utc_30
  • date_us_30
  • date_de_180
  • date_utc_180
  • date_us_180
  • datetime
  • time
  • unix_timestamp
  • last_execution
  • last_execution_succeeded
  • last_execution_start_date
  • last_execution_end_date
  • last_execution_success
  • last_execution_success_start_date
  • last_execution_success_end_date
  • flow_run_triggered_by
These variables and functions are only available in Actions:
  • unix_time() - Same as unix_timestamp in Flows

Ignore http errors - (Deprecated)

This functionality is deprecated, instead custom error handling should be used (no special Connector Action setup needed)
The following field `ignore_http_errors` can be included on any endpoint in order to exclude http errors. Like this
{
"ignore_http_errors": {
"type": "switch",
"title": "Ignore http Errors"
}
}