ZIS custom actions
A custom action is a wrapper for an HTTP request. You can use a custom action in an Action state to make API requests to Zendesk or a third-party service, such as Slack or Shopify. Custom actions are scoped to a ZIS integration, which is defined by the integration key.
Defining a custom action
To use a custom action, you must define the action as a separate resource in the ZIS bundle. The following example defines a custom action that posts a message to an external API.
"external_api.post_message": {
"type": "ZIS::Action::Http",
"properties": {
"name": "external_api.post_message",
"definition": {
"method": "POST",
"url.$": "$.external_api_url",
"requestBody": {
"text.$": "$.message"
}
}
}
}
Using a custom action in an Action state
To call a custom action in an Action state, use
"zis:INTEGRATION:action:CUSTOM_ACTION_NAME" in the state's ActionName
. Replace
"INTEGRATION" with your integration key. Replace "CUSTOM_ACTION_NAME" with the
properties.name
value from the custom action definition. Example:
"PostTicketCreatedMessageToExternalApi": {
"Type": "Action",
"ActionName": "zis:example_integration:action:external_api.post_message",
"Parameters": {
"external_api_url": "EXTERNAL_API_URL",
"message.$": "A new ticket has been created with ID {{$.input.ticket_event.ticket.id}}!"
},
"Next": "NextState"
}
Important: The custom action definition must be in the same bundle as the Action state. An Action state can't call an action from another bundle.
Supported properties for action definitions
A custom action definition supports the following properties.
Name | Type | Mandatory | Description |
---|---|---|---|
type | string | true | Name of the resource. For custom action definitions, this value must be "ZIS::Action::Http" |
properties | object | true | Properties for the resource |
properties.name | string | true | Unique name for the action within the integration. Must match the key for the resource. Can be up to 20 characters consisting of lowercase letters (a-z), uppercase letters (A-Z), numbers, and the underscore character (_) |
properties.definition | object | true | Defines the HTTP request for the action |
properties.definition.method | string | true | HTTP method for the request. Valid values are "GET", "HEAD", "PUT", "POST", "DELETE", "OPTIONS", "PATCH", and "TRACE" |
properties.definition.url | string | Requires either url or path | URL of the HTTP request. Can't be used with path . See Specifying a request path or URL |
properties.definition.path | string | Requires either url or path | Relative path to a Zendesk API endpoint. Can't be used with url . See Specifying a request path or URL |
properties.definition.connectionName | string | false | Name of the connection used to authorize the HTTP request. See Using a connection to authenticate API requests in a ZIS flow |
properties.definition.headers | array of objects | false | Header values for the HTTP request. Formatted as an array of objects with key and value properties. See Accepted HTTP header values |
properties.definition.queryParams | array of objects | false | Query parameters for the HTTP request. Formatted as an array of objects with key and value properties |
properties.definition.contentType | string | false | Media type of the HTTP request body. Valid values are "application/json" and "application/x-www-form-urlencoded". Defaults to "application/json" |
properties.definition.requestBody | object | false | Body of the HTTP request |
Specifying a request path or URL
When you define a custom action, you specify the HTTP request URL using
the path
or url
option.
To make a Zendesk API request to the integration's Zendesk instance, use the
path
option. ZIS automatically resolves the instance's subdomain and host
domain. For example, ZIS resolves a path
of "/api/v2/tickets/123" to
"httpspath
value.
To make a request to an external site or another Zendesk instance, use the url
option. The url
value must be an absolute URL, such as
"https
Accepted HTTP header values
The headers
option contains HTTP headers for the request as an array of JSON
objects. Each object contains a single key-value pair. The key is the HTTP
header name. The value is the HTTP header value.
For a ZIS custom action, an HTTP header name can only contain:
-
Alphanumeric characters (a-z, A-Z, 0-9)
-
The following special characters:
!
,#
,$
,%
,&
,'
,*
,+
,-
,.
,^
,_
,`
,|
,~
An HTTP header value can only contain visible characters, tabs, and spaces.
Passing parameters to a custom action
When you define a custom action, you can use a
JSONPath to create a placeholder for
a value. When you call the action, use the Action state's Parameters
to pass a
value for the placeholder.
For example, the following custom action definition contains the "$.message" placeholder.
"example.post_new_user_message": {
"type": "ZIS::Action::Http",
"properties": {
"name": "example.post_new_user_message",
"definition": {
"method": "POST",
"url.$": "https://example.com",
"requestBody": {
"text.$": "$.message"
}
}
}
}
The following Action state passes a value for "$.message" in Parameters
. When
run, the state replaces the "$.message" placeholder with this value.
"PostNewUserMessageToExampleSite": {
"Type": "Action",
"ActionName": "zis:example_integration:action:example.post_new_user_message",
"Parameters": {
"message.$": "A new user has been created for {{$.input.user_event.user.email}}."
},
"Next": "NextState"
}
Note: You can't use parameter placeholders in JSON property keys. Instead, use a Transform action to create an object that uses a reference path as a key. You can then pass this object as a parameter value. For an example, see ZIS bundle: Creating an HTTP request body using jq.
Authenticating API requests for an action
You can use a connection to authenticate API requests for a custom action. A connection contains credentials for a service or system, such as Slack or Zendesk. See Understanding connections.
Verifying requests with ZIS JWTs
You can use JSON Web Tokens (JWTs) to verify that a request comes from a ZIS
integration. When a custom action makes a request to a non-Zendesk URL, ZIS
includes a JWT in the X-ZIS-Authorization
request header. You can verify the
JWT's signature using the integration's JWT public key. You receive this key
when you register the
integration.
For an example of this setup, see Using JWTs to verify requests from
ZIS.
Note: ZIS JWTs aren't interchangeable with Zendesk Apps framework (ZAF)
JWTs.
ZIS JWT signatures use the RS256 signing algorithm. ZAF JWT signatures only
support the HS256 signing algorithm. ZIS only sends ZIS JWTs in the
X-ZIS-Authorization
request header. You can send ZAF JWTs in any request
header.
ZIS JWT claims
A ZIS JWT's payload contains the following claims.
Name | Type | Description |
---|---|---|
exp | integer | Unix timestamp (seconds since the Unix epoch) for the JWT's expiration. For ZIS JWTs, the exp is 5 minutes after the iat |
iat | integer | Unix timestamp when the JWT was issued |
iss | string | Issuer of the JWT. For ZIS JWTs, the iss is "zis" |
Capturing your action's response in the ResultPath
To use the response from your action, specify a ResultPath
. If the HTTP response is in JSON, the payload is available in "$.{{YOUR_RESULT_PATH}}". Otherwise, the response is available in "$.{{YOUR_RESULT_PATH}}.__httpresponse".
In this example, an action searches for a Zendesk ticket with a specific ID:
"zendesk.get_ticket_by_id_action":{
"type":"ZIS::Action::Http",
"properties":{
"name":"zendesk.get_ticket_by_id_action",
"definition":{
"method":"GET",
"path.$":"/api/v2/tickets/{{$.ticket_id}}.json",
"connectionName": "zendesk"
}
}
}
This can be referenced in a flow. Example:
"GetTicketByID": {
"Type": "Action",
"ActionName": "zis:example_integration:action:zendesk.get_ticket_by_id_action",
"Parameters": {
"ticket_id.$": "$.ticket_id"
},
"ResultPath": "$.get_ticket_by_id_result",
"Next": "UseMyTicketResults"
}
In the above example, if the Zendesk API finds and returns a ticket with the corresponding ID, the ticket payload is available to the UseMyTicketResults
state in "$.get_ticket_by_id_result".
JSON array responses
If the root object of the action's response is a JSON array, you must set ResultPath
to a non-root path. For example, ResultPath
may be "$.my_result" but not "$".
Example action response with a JSON array as the root object:
[
{
"id": 1,
"name": "John Smith"
},
{
"id": 2,
"name": "Jane Smith"
}
]
Failure to set a non-root ResultPath
will cause states later in the flow to not be able to resolve metadata, such as "$.account_id" and "$.input".
Handling errors
If a custom action's HTTP request fails or receives a non-2xx HTTP response status code, the Action state returns a runtime error. By default, this causes the entire ZIS flow to fail.
If a custom action's HTTP request receives a 429 or 500 HTTP response status code, ZIS will attempt to retry the failed flow. See ZIS flow retry logic.
You can use a Catch
block to avoid failing a ZIS flow when an Action state
returns a runtime error. See Using a Catch
block.
Making data accessible to actions in flows
Flows have access to a JSON object which includes the triggering event's payload ("$.input"), "$.account_id", "$.subdomain", and "$.integration_key". You can add objects to the "$." object using the ResultPath
of an action, making data from one state available to subsequent states.
Limitations
-
A custom action can't receive a response payload that exceeds 2 MB. If a response exceeds this limit, the Action state returns a runtime error. See Flow states retry and error handling
-
HTTP requests for custom actions have a 10-second timeout. If a request doesn't receive a response within the timeout period, the Action state returns a runtime error. See Flow states retry and error handling
Additional information
- Sample custom actions in ZIS examples
- Using JWTs to verify requests from ZIS