Apps Development (beta)

Basic Connection - Reference Documentation

Connection is a link between Integromat and 3rd party service/app.

Use this account when authenticating via an API key, username/password, or when your service does not support OAuth 1/2.

Index

Communication

Specification

{
    "url": String,
    "encodeUrl": Boolean,
    "method": Enum[GET, POST, PUT, DELETE, OPTIONS],
    "qs": Flat Object,
    "headers": Flat Object,
    "body": Object|String|Array,
    "type": Enum[json, urlencoded, multipart/form-data, binary, text, string, raw]
    "ca": String
    "condition": String|Boolean,
    "temp": Object,
    "response": {
        "type": Enum[json, urlencoded, xml, text, string, raw, binary, automatic]
        or
        "type": {
            "*": Enum[json, urlencoded, xml, text, string, raw, binary, automatic],
            "[Number[-Number]]": Enum[json, urlencoded, xml, text, string, raw, binary, automatic]
        },
        "temp": Object,
        "data": Object,
        "uid": String, // available only in info section
        "metadata": { // available only in info section
            "type": Enum[text, email],
            "value": String
        },
        "valid": String|Boolean,
        "error": String,
        or
        "error": {
            "message": String,
            "type": Enum[RuntimeError, DataError, RateLimitError, OutOfSpaceError, ConnectionError, InvalidConfigurationError, InvalidAccessTokenError, IncompleteDataError, DuplicateDataError]
            "Number": {
                "message": String,
                "type": Enum[RuntimeError, DataError, RateLimitError, OutOfSpaceError, ConnectionError, InvalidConfigurationError, InvalidAccessTokenError, IncompleteDataError, DuplicateDataError]
            }
        }
    }
}

You can make multiple requests by placing above objects in an array.

Making requests

In order to make a request you have to specify at least a url. All other directives are not required.

All Available request-related directives are shown in the table below:

Key Type Description
url IML String Specifies the URL that should be called.
encodeUrl Boolean Default: true. Specifies if the URL should be auto encoded or not.
method IML String Specifies the HTTP method, that should be used when issuing a request.
headers IML Flat Object A single level (flat) collection, that specifies request headers.
qs IML Flat Object A single level (flat) collection that specifies request query string parameters.
ca IML String Custom Certificate Authority
body Any IML Type Specifies a request body.
type String Specifies how data are serialized into body.
temp IML Object Creates/updates the temp variable
condition IML String or Boolean Determines if to execute current request or never.
followRedirects Boolean Default: true. Follow HTTP 3xx responses as redirects
followAllRedirects Boolean Default: true. Follow non-GET HTTP 3xx responses as redirects
response Response Specification Collection of directives controlling processing of the response.

url

Required: yes
Default: empty

This directive specifies the request URL.

It must be always present. The connection does not support request-less/static mode, because it makes no sense for this particular module.

encodeUrl

Required: no
Default: true

This directive controls the encoding of URLs. It is on by default, so if you have any special characters in your URL, they will be automatically encoded. But there might be situations where you don’t want your URL to be encoded automatically, or you want to control what parts of the URL are encoded. To do this, set this flag to false.

For example you might have a URL component that includes a / and it must be encoded as %2F, but Apps treat your slashes as URL path delimiters by default. I.e. you need the URL to look like https://example.com/Hello%2FWorld, but instead it looks like https://example.com/Hello/World, which is a totally different URL. So the obvious solution would be to just use {{encodeURL(parameters.component)}}. But when you do that, you will receive %252F, because you URL is encoded twice: once by you in your IML expression, and the second time by Apps. To disable this behaviour set this flag to false.

method

Required: no
Default: GET
Values: GET, POST, PUT, DELETE (and other HTTP methods)

This directive specifies the HTTP method that will be used to issue the request. Possible values are GET (default), POST, DELETE, PUT, etc. You can specify the method with an IML expression based on module parameters, like so:

{
    "url": "http://example.com/entity",
    "method": "{{if(parameters.create, 'POST', 'PUT')}}" 
}

headers

Required: no
Default: empty

This directive specifies headers that will be sent with the request. All header names are case insensitive, so x-requested-with is the same as X-Requested-With.

Example:

{
    "url": "http://example.com/data",
    "headers": {
        "X-Item-Id": "{{parameters.id}}"
    }
}

qs

Required: no
Default: empty

This directive specifies the query string to use when making the request.

Note: When specifying this directive, the original query string specified in the URL will be lost. The qs directive takes precedence over query string specified in the URL. Example:

{
    "url": "http://example.com?foo=bar&baz=qux",
    "qs": {
        "foo": "foobar",
        "hello": "world"
    }
}

This will issue a request to this URL: http://example.com?foo=foobar&hello=world. Notice that all the parameters from the original URL were replaced by the parameters specified in qs directive.

Note 2: When specifying qs as an empty object, it means that you want to erase all query string parameters. Example:

{
    "url": "http://example.com?foo=bar&baz=qux",
    "qs": {}
}

This will issue a request to this URL: http://example.com. Notice that all the query string parameters from the original URL were removed. That is because qs directive takes precedence over url query string parameters. If you want to specify query string parameters in the url, you should remove the qs directive.

body

Required: no
Default: empty

This directive specifies the request body when the method directive is set to anything except GET. If the body is specified and the method directive is set to GET - body is ignored and appropriate Content-Type headers are not set.

Example:

{
    "url": "http://example.com/post",
    "body": {
        "first_name": "{{parameters.firstName}}",
        "last_name": "{{parameters.lastName}}"
    }
}

Note: If you want to specify XML request body, you can specify it as a string that will use IML expressions to pass values to XML nodes. Example:

{
    "url": "http://example.com/post",
    "body": "<request><rows><row><column name=\"first_name\">{{parameters.firstName}}</column><column name=\"last_name\">{{parameters.lastName}}</column></row></rows></request>"
}

type

Required: no
Default: json
Values: json, urlencoded, multipart/form-data, text (or string or raw), binary.

This directive specifies how the request body will be encoded and send with the request, when the method is anything but GET: POST, PUT, etc.

When the method is GET this directive will be ignored.

Note: When using text (or string or raw) the body should be a string. If it is not, it will be converted to string.

Note 2: When using json or multipart/form-data or urlencoded the appropriate value of Content-Type header will be set automatically based on what type you have specified.

temp

Required: no
Default: empty

The temp directive specifies an object, which can be used to create custom temporary variables. It also creates a temp variable in IML, through which you then access your variables. The temp collection is not persisted and will be lost after the module is done executing.

This directive is executed prior to everything else: before condition, url, qs, body or any other directive. This makes it a good place to store some values that you need receptively.

When you have multiple requests, this directive is also useful for passing values between requests.

Note: When specifying temp directives in different requests and in the response section (response.temp directive), the contents of the temp collection is not overwritten, but instead merged. Example:

[
    {
        "temp": {
            "foo": "bar"
        },
        "response": {
            "temp": {
                "foo": "baz",
                "hello": "world"
            }
        }
    },
    {
        "temp": {
            "param1": "bar-{{temp.foo}}", // will be "bar-baz"
            "param2": "hello, {{temp.hello}}" // will be "hello, world"
        },
        "response": {
            "temp": {} // will have the foillowing properties:
                       // temp.foo == "baz"
                       // temp.hello == "world"
                       // temp.param1 == "bar-baz"
                       // temp.param2 == "hello, world"
        }
    }
]

condition

Required: no
Default: true

This directive specifies whether to execute the request or not.

If this directive is not specified - the request will always be executed.

If the value of this directive is false, then the request will not be executed, and the flow will go to next request, if present, or return nothing.

When you need to return some data when the condition is false, you are able to specify the condition directive as an object, in which case it will have the following properties:

Key Type Description
condition IML String Specifies if to execute the request or not
default Any IML Type Specifies the module output when the condition is false

condition.condition

Required: no
Default: empty

The original condition directive. If the condition is not specified, the request is always executed.

condition.default

Required: no
Default: empty

An optional module output when the condition is false.

followRedirects

Required: no
Default: true

This directive specifies whether to follow GET HTTP 3xx responses as redirects or never.

followAllRedirects

Required: no
Default: true

This directive specifies whether to follow non-GET HTTP 3xx responses as redirects or never.

Multiple Requests

Making multiple requests is easy - you just have to put all your request objects in an array. All requests will be executed sequentially and the output of last request will be used as the module’s output.

Example:

[
    {
        "url": "http://example.com/api/user",
        "response": {
            "temp": {
                "username": "{{body.username}}"
            }
        }    
    },
    {
        "url": "http://example.com/items",
        "response": {
            "iterate": "{{body}}",
            "output": {
                "username": "{{temp.username}}",
                "text": "{{item.text}}"
            }
        }
    }
]

Handling responses

Connections don’t have any output. They are used to authenticate the user in a remote service and to store data about this authentication, like an API key, or access key or anything else.

Below is the collection of directives controlling processing of the response. All of them must be placed inside the response collection.

Key Type Description
type String or Type Specification Specifies how data are parsed from body.
valid IML String An expression that parses whether the response is valid or not.
error IML String or Error Specification Specifies how the error is shown to the user, if it would occur.
temp IML Object Creates/updates variable temp which you can access in subsequent requests.
data IML Object Updates this connection’s data
metadata Metadata Specification Updates this connection’s metadata
uid IML String An expression that parses user’s id from response body.

type

Required: no
Default: automatic (based on Content-Type header)
Values: automatic, json, urlencoded, text (or string or raw), binary and xml.

This directive specifies how to parse the data received from the server.

When automatic is used for the response type, Integromat tries to parse the response based on it’s Content-Type header. Currently, Integromat recognizes only text/plain, application/json, application/x-www-form-urlencoded and application/xml(or text/xml). When specifying other types, Integromat ignores the Content-Type header and tries to parse the response in the format that you have specified.

Simple example:

{
    "response": {
        "type": "json"
    }
}

This will parse all responses as JSON.

You can specify the type as a string, in which case every response, no matter the status code, will be processed based on your selected type.

Custom response types based on status code

You can also specify type as a special object, where keys are status codes, wildcard or status code ranges. This was made because some services return different responses with different status codes: JSON on success and TEXT on error, for example.

Type object specification:

  • The * (wildcard) represents all responses and should be always present.
  • The [number]-[number] represents a status code range
  • The [number] represents a status code
    Note that when specifying ranges, when multiple ranges include the same status code, the smallest range is selected. The * has the largest range (1-999) and a number has the smallest range, for example 455 is 455-455 range.
    Ranges are counted inclusive from both sides, so if you specify a range 401-402, both the 401 and 402 status codes will be processed by this range.

Example:

{
    "response": {
        "type": {
            "*": "json", // parse all responses as JSON
            "400-408": "text", // parse all 400-408 responses as text, overrides "*",
            "406": "xml" // parse the 406 response as XML, overrides above definitions
        }
    }
}

If a response comes with status 406, it will be parsed as XML
If a response comes with status 401, it will be parsed as text
If a response comes with status 200, it will be parsed as JSON

XML type

Please note that it is not possible to convert XML to JSON objects 1-to-1. That’s why there are some tricks to accessing nodes and attributes to parsed XML in Integromat.

Everything is an array

First of all, each parsed node is an array, even the root node. Even if in XML a node was single, it will still be represented in Integromat as array. Example:

<data>
    <text>Hello, world</text>
</data>

Will be parsed in Integromat as:

{
    "data": {
        "text": ["Hello, world"]
    }
}

So in order to access the value of <text> node in, for example, output, one would write this:

{
    "response": {
        "output": "body.data[].text[]"
    }
}

Note the [] notation. This is a shortcut to get the first element of an array in IML.

Accessing value of a node with attributes

If there are attributes present on the node you want to get value of, then you will have to use _value on it. Example:

<data>
    <text foo="bar">Hello, world</text>
</data>

Here, the previous example will not work, because the <text> node has attributes. Here is what you might use to access the value of the <text> node:

{
    "response": {
        "output": "body.data[].text[]._value"
    }
}
Accessing node attributes

In a similar manner you can access node attributes with _attributes:

<data>
    <text foo="bar">Hello, world</text>
</data>

Note, that _attributes is a collection, where you can access each attribute’s value by it’s name like so:

{
    "response": {
        "output": "body.data[].text[]._attributes.foo"
    }
}
Accessing nested nodes

When accessing nested XML nodes, one must make sure to access them via the array notation. Also, when accessing nested elements, it doesn’t matter if the parent has attributes or no:

<data>
    <items length="2">
        <item>
            <name>Foo</name>
        </item>
        <item>
            <name>Bar</name>
        </item>
    </items>
</data>

If you would then want to process these 2 items in the iterate directive, you would then write something like this:

{
    "response": {
        "iterate": "body.data[].items[].item",
        "output": {
            "name": "{{item.name[]}}"
        }
    }
}

Please note, that it is the item array that contains <item> nodes, and not the items array.

valid

Required: no
Default: true

This directive lets you decide if the response returned by a service is valid or not. Some services might return an HTTP status code >= 400 if there was an error, but some might return < 400 status code and indicate an error in the response body or headers. In the latter case it makes no sense to output anything from the module, but instead indicate that there was an error. That’s when you use this directive.

If this directive is not present, the response is considered always valid when the status code is between 200 and 399. If this directive evaluates to a falsy (false, undefined, null etc.) value, the control is given to the error directive. Otherwise the module will continue the execution normally.

error

Required: no
Default: empty

The error directive specifies the error type and the error message to show the user. In it’s simplest form, it only specifies the error message:

{
    "response": {
        "error": "{{body.error.message}}"
    }
}

The message contained in body.error.message will then be shown to the user, if the request will fail with an error, or a response with status code >= 400 will be received.

You are also able to to specify different error messages based on different status codes. The error object has the following attributes:

Key Type Description
message IML String An expression that parses an error message from response body.
type IML String An expression that specifies the error type.
<status code> Error Specification An object that customizes the error message and type based on the status code.

error.message

Required: yes
Default: empty

The error.message directive specifies the message that the error will contain. It can be a statically specified string, or it can point to a message in, for example, response body or headers.

error.type

Required: no
Default: RuntimeError

The error.type directive specifies a type of the error message. Different error types are handled differently by Integromat. The default error type is RuntimeError. You can read about all available error types in the list below.

Available Error Types

  • RuntimeError - Primary error type. Execution is interrupted and rolled back.
  • DataError - Incoming data is invalid. If incomplete executions are enabled, execution is interrupted and the state is stored. User is able to repair the data and resume execution.
  • RateLimitError - Service responded with rate-limit related error. Applies delay to next execution of a scenario.
  • OutOfSpaceError - User is out of space.
  • ConnectionError - Connection related problem. Applies delay to next execution of a scenario.
  • InvalidConfigurationError - Configuration related problem. Deactivates the scenario and notifies the user.
  • InvalidAccessTokenError - Access token related problem. Deactivates the scenario and notifies the user.
  • IncompleteDataError - Incoming data is incomplete.
  • DuplicateDataError - Reports error as warning, does not interrupt execution. If incomplete executions are enabled, execution is interrupted and the state is stored. User is able to repair the data and resume execution.

error.<status-code>

Required: no
Default: empty

You are able to specify custom errors for different status codes by specifying the status code as the key in the error directive object, and using the same error specification as a value. See examples below.

Examples:

Here is a simple example of an error message with type

{
    "response": {
        "error": {
            "type": "DataError",
            "message": "{{body.message}}"
        }
    }
}

This will output an error of type DataError with message contained in body.message

A more complex example including multiple status codes:

{
    "response": {
        "error": {
            "type": "RuntimeError",
            "message": "Generic error message",
            "400": {
                "type": "DataError",
                "message": "Your request was invalid"
            },
            "500": {
                "type": "ConnectionError",
                "message": "The server was not able to handle your request"
            }
        }
    }
}

temp

Required: no
Default: empty

The temp directive in response section specifies an object, which can be used to create custom temporary variables. It also creates a temp variable in IML, through which you then access your variables. The temp collection is not persisted and will be lost after the module is done executing.

This directive is executed after the request has been made, but prior to everything else in the response section: condition, iterate, output or any other response directive

When you have multiple requests, this directive is also useful for passing values between requests.

Note: When specifying temp directives in different requests and in the response section, the contents of the temp collection is not overwritten, but instead merged. Example:

[
    {
        "temp": {
            "foo": "bar"
        },
        "response": {
            "temp": {
                "foo": "baz",
                "hello": "world"
            }
        }
    },
    {
        "temp": {
            "param1": "bar-{{temp.foo}}", // will be "bar-baz"
            "param2": "hello, {{temp.hello}}" // will be "hello, world"
        },
        "response": {
            "temp": {} // will have the following properties:
                       // temp.foo == "baz"
                       // temp.hello == "world"
                       // temp.param1 == "bar-baz"
                       // temp.param2 == "hello, world"
        }
    }
]

data

The data directive saves data to the connection so that it can be later accessed from a module through the connection variable. It functions similarly to the temp directive, except that data is persisted to the connection.

Example:

{
    "response": {
        "data": {
            "accessToken": "{{body.token}}"
        }
    }
}

This accessToken can be later accessed in any module that uses this connection like so:

{
    "url": "http://example.com",
    "qs": {
        "token": "{{connection.accessToken}}"
    }
}

metadata

The metadata directive allows you to save user’s name or username (or any other text field) so that multiple connections of the same type could be easily recognized. A common practice is to save either username or email or full name to metadata.

The metadata object has 2 properties: value and type. value is used to store the value and type is used to specify what the value is. Currently there are only 2 types: email and text.

Example:

{
    "response": {
        "metadata": {
            "value": "{{body.data.username}}",
            "type": "text"
        }
    }
}

uid

This directive allows you to save the user’s remote service Id. This is required when using Shared Webhooks.

Example:

{
    "response": {
        "uid": "{{body.data.id}}"
    }
}

IML variables

The IML variables are variables that you are able to use in IML expressions.

These IML variables are available for you to use everywhere in this module:

  • now - Current date and time
  • environment - TBD
  • temp - Contains custom variables created via temp directive

  • parameters - Contains connection’s input parameters.
  • common - Contains connection’s common data collection.
  • data - Contains connections’s data collection.
  • oauth.scope - Contains an array of scope required to be passed to OAuth2 authorization process.
  • oauth.redirectUri - Contains redirect URL for OAuth2 authorization process.

Error handling

In every module or connection, you are able to specify 2 directives in the response section that are responsible for handling errors: valid and error.

HTTP 4** and 5** error handling

When the response is returned with 4** or 5** HTTP Status Code, this is automatically considered as an error. If the error directive is not specified, the user will see a message for the status code that was returned (List of HTTP status codes). But you are able to customize the message, shown to the user with the error or error.message directive.

HTTP 2** and 3** error handling

Some APIs signal about an error with a 200 status code and a flag in the body. For this scenario, there is a valid directive, which tells that the response is valid or not.

Custom error handling based on status codes

You are also able to further customize what error message will be shown to the user based on the status code. To do that, just add your status code to the error directive and fill it in as one:

{
    "response": {
        "error": {
            "message": "Generic error message",
            "400": {
                "message": "Your request was invalid"
            },
            "500": {
                "message": "The server was not able to handle your request"
            }
        }
    }
}

Examples

Simple error message:

{
    "response": {
        "error": "{{body.message}}"
    }
}

Message and type:

{
    "response": {
        "error": {
            "type": "DataError",
            "message": "{{body.message}}"
        }
    }
}

Parameters

Parameters describe what your module or connection will receive as input from the user.

[
    {
        "name": "myText",
        "type": "text",
        "label": "Text Field",
        "help": "This is my text field",
        "required": true
    },
    {
        "name": "myNumber",
        "type": "number",
        "label": "Numeric Field",
        "help": "This is my numeric field",
        "advanced": true
    },
    {
        "name": "myBoolean",
        "type": "boolean",
        "label": "Boolean Field",
        "help": "This is my Boolean Field",
        "editable": true
    },
    {
        "name": "myArray",
        "type": "array",
        "label": "Array Field",
        "help": "This is my Array of Strings Field",
        "editable": true
    },
    {
        "name": "myCollection",
        "type": "collection",
        "label": "Collection Field",
        "help": "This is my Collection Field",
        "spec": [
            {
                "name": "greeting",
                "type": "text",
                "label": "Greeting",
                "required": true
            },
            {
                "name": "name",
                "type": "text",
                "label": "Name",
                "required": true
            }
        ]
    }
]

For detailed description of parameters and their types see Parameters

Common data

Common data is a collection to store non-user-specific sensitive values like salts or secrets. Only connections can access this collection.