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.

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"      }    }  }}

Custom actions are scoped to a ZIS integration, which is defined by the integration key. This scope can lead to unexpected results if both of the following conditions apply:

  1. Actions with the same name are defined in two or more bundles
  2. The flows in each bundle reference the same integration key and action name (in other words, the bundles are part of the same integration)

For example, the following identical ActionName could be specified in the flows of two bundles that make up an integration:

"ActionName": "zis:my_integration_key:action:external_api.get_tickets",

At runtime, the action definition in the bundle that was uploaded last is the one that will be executed in the flows of both bundles.

To avoid problems, make sure different actions have unique names in the bundles that are part of the same integration.

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 "https://my_subdomain.zendesk.com/api/v2/tickets/123". ZIS ignores any subdomain or host domain specified in the path 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://abc123.x.pipedream.net" or "https://another_subdomain.zendesk.com/api/v2/tickets/123".

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