Developer commands can execute custom logic to make API requests, parse API responses, and combine multiple commands together.
Each command is described below along with a few examples.
jq
is an open source query language for JSON.
The !jq
command extracts data from a JSON data structure using jq
expressions. The output from
a jq
command can serve as input into other objects.
jqplay is an interactive tool for editing and testing jq expressions.
The !http command makes API requests.
Warning
Authenticated API Requests
When a user connects an integration with a service provider, we utilize
the specified authentication method as indicated in the auth portion of
the configuration file.If the configuration file specified OAuth2 authentication, we will
continue to use the same access token created when the marketer
connected the integration. If the OAuth2 token requires refreshing (and
if the service requires it), we will attempt to refresh the token up to
three times. If the token fails to refresh after three attempts, an
error is recorded and the marketer is notified.
An !http command is defined by the following properties:
Key | JSON Type | Required | Default Value |
---|---|---|---|
path | string | no | |
url | string | no | |
method | string | yes | "GET" |
body | object | no | {} (empty object) |
params | object | no | {} (empty object) |
headers | object | no | {} (empty object) |
This is the URL path that is relative to the base_url value.
This is the full URL path for the request, if used instead of "path", it disregards the base_url value.
The method is the HTTP method that should be used when making an HTTP request to the API end-point.
The method is limited to the following values: GET, POST, PUT, PATCH, DELETE, and OPTIONS.
The body is the body of an HTTP request.
Warning
Currently, we only are able to utilize valid JSON as the body of a request.
In this example, we are using the body key to pass the JSON object to enable a webhook for a resource.
{
"name": "subscribe",
"run": {
"!http": {
"path": "repos/${resource::id}/hooks",
"method": "GET",
"body": {
"enabled": true
}
}
}
}
The params will be appended to the path of an HTTP request.
Warning
Currently, we only are able to utilize valid JSON as the params of a request.
In this example, we are using the param key to provide the sort item. This has the effect of adding the params to the end of the path and the path becomes path?sort=desc.
{
"name": "list",
"run": {
"!http": {
"path": "repos",
"method": "GET",
"params": {
"sort": "desc"
}
}
}
}
The headers will be added to the headers of an HTTP request.
Warning
Currently, we only are able to utilize valid JSON as the headers of a request.
In this example, we are using the headers key to specify the content-type of a request.
{
"name": "list",
"run": {
"!http": {
"path": "repos",
"method": "GET",
"headers": {
"content-type": "application/json"
}
}
}
}
Most often the response of an !http
command will be piped to a !jq
as part of a !pipe
command to map the response to a specific format. The entire response of an !http
command can be referenced using .body
. Imagine the response from your API (internally to App Studio) looks something like the following.
{
"body": // the response from your API
}
Note: Use .body for APIs that return Arrays
If your API returns a top-level array, the
.body[]
syntax is required to properly handle the response.
The !pipe command allows multiple commands to be chained in arbitrary order.
When commands are chained, the output of one command becomes the input to the next command.
{
"name": "list",
"run": {
"!pipe": [
{
"!http": {
"path": "repos",
"method": "GET"
}
},
{
"!jq": "[].{name: name, id: id}"
}
]
}
In the above example, the result of the !http command is then passed to the !jq command.
When you need to access output from a command that's not immediately before the current command, you can use a special expansion syntax:
${piped_content::INDEX}
where INDEX is the position of the command. In this example:
${piped_content::0}
refers to the input data for the pipe command${piped_content::1}
refers to the output of the!http
command${piped_content::2}
refers to the output of the!jq
command
All commands can refer to outputs generated before them.
The !resource command allows developers to use resources within ActiveCampaign. Currently supported resources:
- ActiveCampaignContact
To get specific information about an ActiveCampaign resource, such as what fields are available for contacts:
"!resource": "ActiveCampaignContact.fields"
To refer to concrete instances of contacts:
"!resource": "ActiveCampaignContact"
ActiveCampaign Resources
This list describes what can be used with the !resource
command.
ActiveCampaignContact
This resource can access contact data for an ActiveCampaign account. Below are available features.
getting available contact fields
Usage:
"!resource": "ActiveCampaignContact.fields"
Output Example:
[
{
"value": "email", "display": "Email"
},
{
"value": "firstName", "display": "First Name"
},
{
"value": "lastName", "display": "Last Name"
},
{
"value": "phone", "display": "Phone"
}
]
getting concrete contact instances
Usage:
"!resource": "ActiveCampaignContact"
Output Example:
{
"email": "[email protected]",
"firstName": "Edward",
"lastName": "Teach",
"phone": "(123)456-7890"
}
All values entered by users in the UI elements defined by the select
step of a workflow are saved in our system. They can be referenced elsewhere in your configuration using custom_data
substitution variables.
Custom data has the following format:
${custom_data::ID.ATTRIBUTE}
Each custom data reference MUST follow this format: surrounded by an opening {
and closing }
curly braces, and prefixed with a dollar sign $
.
Custom data are stored in a simplified data structure. Since they represent user input, each entry has two keys:
- value: this is the value of user input, it's guaranteed to always exist
- display: this is the label or display users saw when they made a selection in the UI, it exists for all UI elements but "text"
A simplified example of this data structure would look similar to the following:
{
"dropdown-input-1": {
"display": "Apple",
"value": "apple"
},
"text-area-1": {
"display": "",
"value": "user input as text"
}
}
// to access the display of dropdown-input-1:
${custom_data::dropdown-input-1.display}
// to access the value of text-area-1:
${custom_data::text-area-1.value}
If the subdomain field is defined as part of the authentication process, that subdomain value will become available to use elsewhere in your configuration using the subdomain substitution variable.
The subdomain value can be accessed in the following manner:
${subdomain}
There are two options when displaying the subdomain input in the UI:
If the base_url
in the configuration includes the ${subdomain}
substitution variable then the input will appear with the base_url
parts wrapping the input:


Otherwise the input will be shown as:


Example Subdomain Usage:
In the following example, only a portion of a configuration is shown.
{
"$version": "2",
"api": {
"base_url": "https://${subdomain}.example.com"
},
"auth": {
"my_oauth2_configuration": {
"type": "oauth2",
"configuration": {
"authorization_base_url": "https://api.example.com/oauth2/authorize",
"client_id": "woef2qo3hefawWEWrfh2qe21wlvdflkefnqs",
"client_secret": "[insert your secret here]",
"scopes": [
"insert_scope_here_if_needed"
],
"token_url": "https://api.example.com/oauth/token",
"refresh_url": "https://api.example.com/oauth/authorize"
},
"defined_fields": {
"subdomain": {
"label": "Account Subdomain",
"placeholder": "Enter your Account Subdomain",
"help_text": "Your subdomain immediately precedes the .example.com portion of your Example url."
}
}
}
}
}
As can be seen in the example above, the ${subdomain}
variable is being used to replace a portion of the base_url
; however, the ${subdomain}
variable can be used throughout your configuration.
The !save command allows the publisher to save data related to a subscribed resource for future reference.
Usage:
"!save": {"scope": "CHANGEME"}
The scope value should be the same as the data_intake scope set in the data_intake section of the configuration. It can be either workflow, connection or application. Please see the example explained below.
Within your configuration, you may need to store data to variables for later use. These can be saved in our system with the !save command. They can then can be referenced elsewhere in your configuration using data substitution variables. The example use case explained below is to store a webhook_id which will be needed to update and delete a resource's webhook while working with inbound integrations.
Example Usage:
{
"!pipe": [
{
"!http": {"method": "GET", "path": "CHANGEME"}
},
{
"!jq": "{webhook_id: .id}"
},
{
"!save": {"scope": "workflow"}
}
]
}
The !save command will save the !jq output to our system. It can be accessed this way:
${data::workflow::webhook_id}
The format is similar to custom_data format explained above.
Updated 21 days ago