A ZIS link stores a relationship between two data objects. In most cases, the objects are in different systems. For example, you can link a Zendesk ticket id to a Slack message id.

A single ZIS link models a one-to-one relationship. To model a one-to-many relationship, use the same object in multiple links. For example, you can use multiple links to associate a single Zendesk user profile id with several Shopify order ids.

You can use the following built-in actions to manage links in a ZIS flow:

You can create a link using the CreateLink action. The action requires the following parameters:

  • A left_object that contains data for one object in the link
  • A right_object that contains data for the other object in the link
  • A link_type string that describes the relationship between the objects. Several links can share the same link type.

The left_object and right_object parameters also require a name property. The name property contains the data you want to link. Along with the link type, the left object name and right object name uniquely identify a link.

The following state uses a CreateLink action to link a Zendesk ticket id to a Slack message id.

"TicketToMessage.CreateLink": {  "Type": "Action",  "ActionName": "zis:common:action:CreateLink",  "Parameters": {    "link_type": "ticket_to_message_link",    "left_object": {        "name.$": "$.input.ticket_event.ticket.id"    },    "right_object": {      "name.$": "$.post_message_response.message.ts"    }  },  "Next": "NextState"}

The action creates a link in the ZIS Links Service. The action scopes the link to the ZIS flow's Zendesk account and integration. Example response:

{  "link": {    "account_id": 12345678,    "integration": "INTEGRATION_NAME",    "left_object": {      "name": "1234567"    },    "link_type": "ticket_to_message_link",    "right_object": {      "name": "1234567890.123456"    },    "uuid": "f5a31f96-880f-bede-ddfc-8c9500da090e"  }}

Name attributes

The name property supports key-value pairs called name attributes. You can use name attributes to include several pieces of data in an object's name. Name attributes also let you label the data in a name.

Name attributes require special syntax. To separate an attribute's key and its value, use :. To include multiple name attributes in a name value, use the / separator. Example:

"TicketToMessage.CreateLink": {  "Type": "Action",  "ActionName": "zis:common:action:CreateLink",  "Parameters": {    "link_type": "ticket_to_message_link",    "left_object": {        "name.$": "ticket_id:{{$.input.ticket_event.ticket.id}}"    },    "right_object": {      "name.$": "channel:{{$.send_message_response.message.channel}}/thread_ts:{{$.send_message_response.message.ts}}"    }  },  "Next": "NextState"}

The response includes name attributes in the object's name_attrs property.

{  "link": {    "account_id": 12345678,    "integration": "INTEGRATION_NAME",    "left_object": {      "name": "ticket_id:1234567",      "name_attrs": {        "ticket_id": 1234567      }    },    "link_type": "ticket_to_message_link",    "right_object": {      "name": "channel:zendesk-tickets/thread_ts:1234567890.123456",      "name_attrs": {        "channel": "zendesk-tickets",        "thread_ts": 1234567890.123456      }    },    "uuid": "f5a31f96-880f-bede-ddfc-8c9500da090e"  }}

Metadata

Each object also supports an optional metadata property. You can use the property to store arbitrary data for an object.

"TicketToMessage.CreateLink": {  "Type": "Action",  "ActionName": "zis:common:action:CreateLink",  "Parameters": {    "link_type": "ticket_to_message_link",    "left_object": {        "name.$": "ticket_id:{{$.input.ticket_event.ticket.id}}"    },    "right_object": {      "name.$": "channel:{{$.send_message_response.message.channel}}/thread_ts:{{$.send_message_response.message.ts}}",      "metadata": {        "team_name.$": "$.get_team_info_response.team.name"      }    }  },  "Next": "NextState"}

The response includes a metadata property for the object.

{  "link": {    "account_id": 12345678,    "integration": "INTEGRATION_NAME",    "left_object": {      "name": "ticket_id:1234567",      "name_attrs": {        "ticket_id": 1234567      }    },    "link_type": "ticket_to_message_link",    "right_object": {      "metadata": {        "team_name": "My Corp"      },      "name": "channel:zendesk-tickets/thread_ts:1234567890.123456",      "name_attrs": {        "channel": "zendesk-tickets",        "thread_ts": 1234567890.123456      }    },    "uuid": "f5a31f96-880f-bede-ddfc-8c9500da090e"  }}

You can use the LoadLinks action to look up existing links. The action matches links based on the following parameters:

  • link_type
  • left_object_name
    OR
    right_object_name
    OR
    left_object_name and right_object_name

Note: You can't match links based on an object's metadata.

To use the action's response in later states of the ZIS flow, specify a ResultPath.

"TicketToMessage.LoadLinks": {  "Type": "Action",  "ActionName": "zis:common:action:LoadLinks",  "Parameters": {    "link_type": "ticket_to_message_link",    "left_object_name.$": "ticket_id:{{$.input.ticket_event.ticket.id}}"  },  "ResultPath": "$.link_results",  "Next": "NextState"}

The response contains an array of matching links and their count.

{  "count": 1,  "links": [    {      "account_id": 12345678,      "integration": "INTEGRATION_NAME",      "left_object": {        "name": "ticket_id:1234567",        "name_attrs": {          "ticket_id": 1234567        }      },      "link_type": "ticket_to_message_link",      "right_object": {        "metadata": {          "team_name": "My Corp"        },        "name": "channel:zendesk-tickets/thread_ts:1234567890.123456",        "name_attrs": {          "channel": "zendesk-tickets",          "thread_ts": 1234567890.123456        }      },      "uuid": "f5a31f96-880f-bede-ddfc-8c9500da090e"    }  ],  "meta": {    "has_more": false  }}

Later states of the ZIS flow can access the response from the ResultPath. For example, the following state references a name attribute in the links array.

"ThreadMessageOnTicketUpdate": {  "Type": "Action",  "ActionName": "zis:INTEGRATION_NAME:action:PostToSlack",  "Parameters": {    "thread_ts.$": "$.link_results.links[0].right_object.name_attrs.thread_ts",    "text.$": "$.input.ticket_event.comment.body"  },  "Next": "NextState"}

Wildcard matching

In a LoadLinks action, the left_object_name and right_object_name parameters support values with a trailing wildcard (*). You can use a trailing wildcard to match an object name based on a prefix.

Note: The wildcard must be the last character in the value. A value of only "*" is not supported.

For example, the following state uses a LoadLinks action with a trailing wildcard in the left_object_name parameter. The action matches links with a left object name that begins with "ticket_id:".

"TicketToMessage.LoadLinks": {  "Type": "Action",  "ActionName": "zis:common:action:LoadLinks",  "Parameters": {    "link_type": "ticket_to_message_link",    "left_object_name": "ticket_id:*"  },  "ResultPath": "$.link_results",  "Next": "NextState"}

Cursor pagination

By default, a LoadLinks response can contain up to 20 matching links per page. Use the page_size parameter to specify the number of links to return per page. The maximum value is 100.

"TicketToMessage.LoadLinks": {  "Type": "Action",  "ActionName": "zis:common:action:LoadLinks",  "Parameters": {    "link_type": "ticket_to_message_link",    "left_object_name.$": "ticket_id:{{$.input.ticket_event.ticket.id}}",    "page_size": 30  },  "ResultPath": "$.link_results",  "Next": "NextState"}

If a LoadLinks action returns paginated results, the meta.has_more property is true. Paginated results also contain a meta.after property, a meta.before property, or both. The meta.after and meta.before properties contain link ids that act as cursor values.

{  "count": 30,  "links": [    {      "account_id": 12345678,      "integration": "INTEGRATION_NAME",      "left_object": {        ...      },      ...    }  ],  "meta": {    "after": "01GYCRPVNTTQXZ1Y14Y9YE02QQ",    "before": "01GYCS199Q6SPGXARSQK6ZVKR0",    "has_more": true  }}

To retrieve the next or previous page of results, use the cursor values in the respective page_after_cursor or page_before_cursor parameter of a LoadLinks action.

"TicketToMessage.LoadLinks": {  "Type": "Action",  "ActionName": "zis:common:action:LoadLinks",  "Parameters": {    "link_type": "ticket_to_message_link",    "left_object_name.$": "ticket_id:{{$.input.ticket_event.ticket.id}}",    "page_size": 30,    "page_after_cursor": "01GYCRPVNTTQXZ1Y14Y9YE02QQ"  },  "ResultPath": "$.link_results",  "Next": "NextState"}

When you reach the last page of results, the meta.has_more property is false.

{  "count": 1,  "links": [    {      "account_id": 12345678,      "integration": "INTEGRATION_NAME",      "left_object": {        ...      },      ...    }  ],  "meta": {    "before": "01GYCS11C5DJRJTF2J3QG03NMR",    "has_more": false  }}

If the LoadLinks action finds no matching links, the response returns a count of "0" and an empty links array.

{  "count": 0,  "links": [],  "meta": {    "has_more": false  }}

You can use the count to determine if a link already exists. For example, the following Choice state adds branching logic based on a link count.

"TicketToMessage.LinkChoice": {  "Type": "Choice",  "Choices": [    {      "Variable": "$.link_results.count",      "NumericEquals": 0,      "Next": "SendMessageOnTicketCreate"    },    {      "Variable": "$.link_results.count",      "NumericEquals": 1,      "Next": "ThreadMessageOnTicketUpdate"    }  ],  "Default": "MultipleLinksError"}

You can use the PatchLink action to make partial updates to objects in a link.

The action requires the link's current link_type, left_object_name, and right_object_name. The action also requires a new right_object, left_object, or both. Any new objects must include a name property. The action only changes the objects and properties you specify.

Note: You can't use the PatchLink action to change the link_type.

For example, the following state uses the PatchLink action to update the name and metadata.org_email_domain of a link's right object. The action doesn't change the left object or other metadata of the right object.

"TicketToMessage.PatchLink": {  "Type": "Action",  "ActionName": "zis:common:action:PatchLink",  "Parameters": {    "link_type": "ticket_to_message_link",    "left_object_name.$": "ticket_id:{{$.input.ticket_event.ticket.id}}",    "right_object_name.$": "channel:{{$.send_message_response.message.channel}}/thread_ts:{{$.send_message_response.message.ts}}",    "right_object": {      "name.$": "channel:{{$.send_message_response.message.channel}}/thread_ts:{{$.send_message_response.message.ts}}",      "metadata": {        "org_email_domain.$": "$.get_team_info_response.team.email_domain"      }    }  },  "Next": "NextState"}

You can use the DeleteLink action to delete a link. The action requires the link's link_type, left_object_name, and right_object_name.

"TicketToMessage.DeleteLink": {  "Type": "Action",  "ActionName": "zis:common:action:DeleteLink",  "Parameters": {    "link_type": "ticket_to_message_link",    "left_object_name.$": "ticket_id:{{$.input.ticket_event.ticket.id}}",    "right_object_name.$": "channel:{{$.send_message_response.message.channel}}/thread_ts:{{$.send_message_response.message.ts}}"  },  "Next": "NextState"}

Rate limits

The built-in link actions make requests to the ZIS Links API. These requests are subject to API rate limits.

Best practices

  • Don't store secrets in ZIS links. Links aren't encrypted and are accessible using the ZIS Links API. Depending on your integration, data in a ZIS link may be accessible in connected systems.