Pull requests
You can provide an endpoint that lets Zendesk Support periodically query for new external resources in the origin system, such as for new comments in Instagram. The queries are known as pull requests or simply pulls. Zendesk Support makes a pull request approximately every 2 minutes.
To enable this feature, you must build a pull endpoint and specify its url in the integration manifest. Example:
"urls": {
"pull_url":"https://omniwear.com/integrations/instagram/pull",
...
}
The endpoint must implement the request and response formats described in this document. Your endpoint is responsible for retrieving the resources in the origin system.
Request format
Zendesk Support makes a request approximately every 2 minutes to the pull_url
endpoint specified in your integration manifest. Zendesk Support includes the following query string parameters in the body of each POST request.
Name | Type | Comment |
---|---|---|
metadata | string | Stringified then URL-encoded data about the integration instance. See Metadata and state |
state | string | Stringified then URL-encoded data about the current state. See Metadata and state |
Examples
The body of a POST request could contain the following data for an Instagram integration service:
metadata=%7B%5C%22instagram_username%5C%22%3A%5C%22omniwear%5C%22%2C%5C%22instagram_oauth_token%5C%22%3A%5C%22xyzabc%5C%22%7D&state=%7B%5C%22last_message_id%5C%22%3A%5C%2220151210082800-erika%5C%22%7D
The URL-encoded query string is a bit hard to read. The decoded string looks as follows:
metadata={\"instagram_username\":\"omniwear\",\"instagram_oauth_token\":\"xyzabc\"}&state={\"last_message_id\":\"20151210082800-erika\"}
If your integration service doesn't use Zendesk Support to store state, the pull request could look as follows:
https://omniwear.com/integrations/instagram/pull?metadata=%7B%5C%22integration_service_info_id%5C%22%3A%5C%22123%5C%22%7D&state=
Decoded string:
metadata={\"integration_service_info_id\":\"123\"}&state=
Response format
Send a response with the following JSON object containing an ordered array of up to 200 external resources. Zendesk Support will process them in order.
Name | Type | Max chars | Mandatory | Comments |
---|---|---|---|---|
external_resources | array | yes | Array of external resources, up to a maximum of 200. See external_resources array below | |
state | string | 5000 | no | Stringified data about the new state. If not returned, the pre-existing state value is retained. See Metadata and state. |
metadata_needs_update | boolean | no | Should the Zendesk Support administrator be asked to revisit the UI for the integration account to reset the metadata? | |
metadata | string | 5000 | no | Stringified data about the integration instance. See Metadata and state |
external_resources array
Each external resource in the array consists of an object with the following properties:
Name | Type | Max chars | Mandatory | Comments |
---|---|---|---|---|
external_id | string | 255 | yes | Unique identifier of the external resource (string). May not include leading or trailing whitespace. Must be ASCII characters |
internal_note | boolean | no | If true, the message is an internal note. If false, the message is a public comment. Defaults to false | |
message | string | 65535 | yes | Text to be converted to a ticket or comment |
html_message | string | 65535 | no | HTML version of message |
parent_id | string | 511 | no | Unique identifier of the external resource for which this is a response. Used to choose the correct thread. Responses may include parent_id or thread_id , but not both. See Conversation threads |
thread_id | string | 511 | no | Arbitrary identifier of the thread to which this item should belong. Responses may include parent_id or thread_id , but not both. See Conversation threads |
created_at | datetime | yes | When the resource was created in the origin system, as an RFC 3339 format date-time. Example: '2015-09-08T22:48:09Z' | |
author | object | yes | See author object below | |
display_info | array | no | Array of integration-specific data used by apps to modify the agent UI. See display_info object below | |
allow_channelback | boolean | no | If false , prevents the agent from making additional comments on the message in the Zendesk Support interface | |
fields | array | no | Array of objects describing a ticket field. See field object below. | |
file_urls | array | no | Array of files to be imported into Zendesk Support. See file urls below. |
author object
Name | Type | Max chars | Mandatory | Comments |
---|---|---|---|---|
external_id | string | 255 | yes | Unique identifier of the user in the origin service. May not include leading or trailing whitespace. |
name | string | 255 | no | If not supplied, defaults to external id |
image_url | string | 255 | no | URL to an image for the user |
locale | string | 255 | no | The user's locale. Must be one of the Zendesk Support supported locales. |
fields | array | no | Array of objects describing a user field. See field object below. |
display_info object
Name | Type | Max chars | Mandatory | Comments |
---|---|---|---|---|
type | string | 255 | yes | Globally unique type identifier defined by the integration service. Examples: a GUID or URI |
data | object | 65535 | yes | JSON data containing display hints |
field object
The field object contains a field ID and value. When Zendesk Support makes a new ticket or user on behalf of the integration service, Zendesk will attempt to set a field values for the item as specified by this object. When creating a comment on an existing ticket, Zendesk Support will ignore the field objects.
The field object looks as follows:
Name | Comments |
---|---|
id | The ID of the field to be specified. A string for system fields, or a string or integer for custom fields. |
value | The value to be assigned to the field |
The ID may refer to a system field. If so, the following values are supported for tickets:
ID | Value |
---|---|
subject | Subject of the ticket to be created |
status | Status of the ticket to be created (e.g. 'open'.) Value should be a recognized Zendesk Support status string. |
type | Type of the ticket to be created (e.g. 'question'.) Value should be a recognized Zendesk Support type string. |
priority | Priority of the ticket to be created (e.g. 'high'.) Value should be a recognized Zendesk Support priority string. |
group | ID of the Zendesk Support group to which the ticket should be assigned |
assignee | ID of the Zendesk Support user to which the ticket should be assigned |
tags | Array of tag strings to be applied to the ticket |
In addition, the following values are supported for users:
ID | Value |
---|---|
notes | Notes on the user |
details | Details about the user |
Alternatively, the ID may refer to a custom field. If so, it may refer to the custom field by ID or name:
ID | Description | Value |
---|---|---|
any integer | The ID of the custom field to be set | The value to apply to the custom field (allowed values will differ from field to field) |
any string | The name of the custom field to be set | The value to apply to the custom field (allowed values will differ from field to field) |
file urls
The file urls array contains URLs to files that will be attached to the Zendesk Support ticket or comment. File URLs are subject to a number of limitations:
- URLs must be HTTPS
- URLs may be relative URLs. If relative, they will be resolved relative to the manifest URL for the integration service.
- Files must be hosted on the same subdomain as the manifest
- A maximum of 10 files per external resource are supported
- The maximum size of a file varies from Zendesk Support account to account
- File downloads are subject to timeouts. Zendesk imposes a timeout on the total conversion process, including API calls and file downloads. This implies that slow API calls will restrict the time available to perform downloads.
When Zendesk imports an external resource, it performs a POST request to each of the file URLs. The body of the request is a JSON object containing the integration instance metadata at the key "metadata" (see Metadata and state). File download failures are not fatal -- they do not stop the import process. A failure to download and process a file does not affect the processing of other files for the same external resource.
Example
{
"external_resources":[
{
"external_id": "20151210083000-amy",
"message": "Please help. My printer is on fire.",
"html_message": "Please help. <b>My printer is on fire.</b>",
"created_at": "2015-09-08T22:48:09Z",
"author": {
"external_id": "a2466",
"name": "Amy",
"image_url": "https://scontent.cdninstagram.com/hphotos-xap1/t51.2885-19/s150x150/12424615_209564492716268_42714239_a.jpg",
"locale": "de",
"fields": [
{ "notes": "A virgo who loves long walks on the beach" }
]
},
"display_info": [{
"type": "omniwear.com/integrations/instagram/display/comment/v1",
"data": "{\"priority\": \"high\"}"
}],
"allow_channelback": false
},
{
"external_id": "20151210083200-bob",
"internal_note": true,
"message": "There is no sand, blanket or fire extinguisher near by.",
"created_at": "2015-09-08T22:48:12Z",
"parent_id": "20151210083000-amy",
"author": {
"external_id": "a2466",
"name": "Amy",
"image_url": "https://scontent.cdninstagram.com/hphotos-xap1/t51.2885-19/s150x150/12424615_209564492716268_42714239_a.jpg",
},
"display_info": [{
"type": "omniwear.com/integrations/instagram/display/comment/v1",
"data": "{\"priority\": \"medium\"}"
}],
"allow_channelback": false
}
],
"state": "{\"last_message_id\":\"20151210083200-bob\"}"
}
Conversation threads
Zendesk Support uses parent_id
or thread_id
to link multiple resources in the external system into conversation threads, which are roughly synonymous with tickets. Integration services can send either argument, or neither. Supplying both is not supported.
- parent_id This describes a ‘reply to’ relationship.
Example: Frank sends an email to Bob. This email has ID 123. Bob replies to Frank. His reply has ID 234. When sending data about Bob's email to Zendesk Support, the external_id
is '234', and the parent_id
is '123'
- thread_id This allows the integration service to designate multiple external resources the same Zendesk Support ticket.
For example, if the customer wants all external resources where the word ‘Endgame’ appears inside the same ticket, the integration service can give ‘thread_endgame’ as the thread_id
to all external resources that match the description. Zendesk Support will put all of them into the same ticket.
If there is no parent_id
and no thread_id
, the external resource becomes a new ticket in Zendesk Support.
If there is a parent_id
and Zendesk Support already has a ticket that includes content from that parent, the external resource becomes a comment of that ticket. If Zendesk Support hasn’t seen the parent_id
before, the external resource becomes a new ticket.
If there is a thread_id
and Zendesk Support already has a ticket for that thread_id
, the external resource becomes a comment on that ticket. If Zendesk Support hasn’t seen the thread_id
before, the external resource becomes a new ticket.
When Zendesk Support creates a new thread for an external resource that does not have a thread_id
, the ID of the new thread will be the external_id
of the resource. For example, suppose Zendesk Support processes the following data:
{"external_id": "234", "parent_id": "123", "message": "Hey, what's up?"}
and Zendesk Support has not seen item 123. it will create a new ticket for "Hey, what's up?", and the thread_id
will be “234”.
If Zendesk Support subsequently processes the following:
{"external_id": "345", "thread_id": "234", "message": "Not much, you?"}
then Zendesk Support will create a comment on the ticket for "Not much, you?"
Duplicated items
If Zendesk Support receives an external resource with an external_id
that it has already seen, it ignores the duplicated or modified external resource. Integration services may freely resend external resources when there is any communication failure.
However, sending the same resources multiple times not only makes the API payload bigger, it also means Zendesk Support needs to do more work to de-duplicate the resources. For performance reasons, it is highly recommended that integration services send each external resource exactly once in normal operation.
Zendesk Support also recognizes external resources that were created by channelback. An integration service does not need to have any logic for distinguishing external resources created by Zendesk Support versus any other external resources. See the channelback response format for more information.
Recognized error responses
There are 2 kinds of errors when handling channel integration.
-
Recoverable - These are errors like throttled or timeout errors. Zendesk Support will retry up to 5 times and will continue polling when the next cycle comes. The following response codes are treated as recoverable errors: Request Timeout (408), Internal Server Error (500), Bad Gateway (502), Service Unavailable (503), and Gateway Timeout (504)
-
Irrecoverable - This includes errors like authentication or version-no-longer-supported errors. Example: 401 Unauthorized. Zendesk Support will stop communicating with the integration service. Zendesk Support will contact the administrator and ask them to upgrade or reauthorize the integration service.
Concurrency
Zendesk Support makes polling calls sequentially. Integration services generally do not need to worry about concurrent polling or channelback requests within a particular instance. However, timeouts or network errors could create scenarios where multiple requests are processed by the integration service for a single integration instance concurrently.
Timeout
Zendesk Support sets a 20-second timeout when pulling content from an integration service. If a pull call times out, Zendesk Support will send the same pull state argument the next time it polls.
Idempotency
Zendesk Support periodically makes API calls to the integration service. Those calls may fail due to network issues or other problems. Zendesk Support will handle failures, and retry failed calls as appropriate. If the integration service is idempotent, then these retries will assure that Zendesk Support receives all content.
Zendesk doesn’t require that the integration service API be strictly idempotent. Repeated calls with the same arguments don’t need to result in exactly the same response. To prevent missing external resources, each response to a repeated call should contain all external resources returned by the earlier response (but could contain more).
Integration services that store state locally need to be careful to make sure external resources are not dropped due to a state change on the integration service. For example, suppose the integration service keeps track of the timestamp of the most recently returned external resource timestamp. It resets this timestamp each time it returns data to Zendesk Support. Subsequent responses include only external resources created after that timestamp. If the integration service returns external resources, but Zendesk Support fails to record them, those external resources will be lost forever. Zendesk suggests that an integration service store a version or timestamp in Zendesk Support state data rather than locally. That way, when Zendesk Support retries a call, the integration service knows which external resources are not yet in Zendesk Support.