API versioning
The Zendesk Messaging platform APIs and webhooks are strictly versioned to avoid unexpected breaking changes in behavior or API signature. When backwards-incompatible changes are unavoidable, a new version will be released to avoid breaking existing integration patterns. Integrators can then opt in to the new version when ready.
Versioning scheme
The versioning scheme supports a major version number (for example, v2) and sometimes a minor version (for example, v1.1). A minor version bump is used when the behavior or expected payload of an API needs to change in a breaking way, but without fundamental changes to how the APIs are used. On the other hand, a major version bump signals that significant changes to the API have been introduced, such as the removal of APIs, major changes in behavior or payload structure, etc.
The current supported versions are v1, v1.1, and v2. While all three versions are still maintained, new integrations should only be built against the latest v2 API suite, except in cases where no functional parity exists.
API versioning
When making calls to the messaging API, the version of the API is specified in the request path. For example:
POST /v2/apps/{app_id}/conversations/{conversation_id}/messages
For more information on how to call the API, see our API quickstart guide.
Webhook versioning
The version of a webhook determines the structure of the payload your backend will receive, as well as the list of available triggers that you can subscribe to. A webhook's version is determined by the version of the API used to create it. For example, when creating a custom integration using the v2 Create Integration API, the resulting webhook will have a version of v2. To create a v1.1 webhook, use the v1.1 Create Webhook API instead.
For more information on how to use webhooks, see receiving messages.
Backwards compatible changes
We consider the following types of changes to be backwards compatible. In other words, these types of changes do not require a new version of the API, and can occur at any time. When coding your integration with Zendesk Messaging, take care to ensure that the types of changes listed below would not break any assumptions you make in your code.
For example, your JSON parsing logic should be configured not to throw an error when an unexpected key is found, or when an enum contains a previously unknown value. Assume also that any JSON field returned as an array may contain multiple items in the future, even if you only see one array entry in practice.
Additive changes
- Adding new fields or HTTP headers to existing API responses and webhook payloads
- Adding new optional fields, query parameters, or HTTP headers to existing API request payloads
- Adding new API endpoints or adding new methods on existing endpoints e.g. adding support for HTTP PUT to an existing API path
- Introducing new types of messages, integrations, clients, or any other typed entity without changing the behavior of existing types
- For example, introducing a new message type of
locationor a new integration type oftwitter. For any code that processes entities with atypeproperty (or equivalent), unknown types should be gracefully handled or ignored
- For example, introducing a new message type of
- Introducing new webhook triggers
- In v2, webhook triggers must be explicitly selected. However, in v1 and v1.1, the wildcard trigger (
*) can be used to subscribe to all available events. When using the wildcard trigger, your code should gracefully handle or ignore any unknown event types
- In v2, webhook triggers must be explicitly selected. However, in v1 and v1.1, the wildcard trigger (
- Adding support for existing webhook triggers and message types as channels adopt new capabilities
- For example, to begin delivering
conversation:readwebhooks for Twitter clients as soon as the channel adopts the read notification capability
- For example, to begin delivering
Formatting changes
- Changing the format or length of primary id fields and keys without exceeding 255 characters
- For example, changing the string format or character length of
user.idorkey.secret
- For example, changing the string format or character length of
- Changing the order of fields in existing API responses and webhook payloads
Relaxing restrictions
- Increasing the size or length restrictions on arrays or strings, or allowing certain characters which were previously disallowed
- Accepting upload and transmission of new file and media types that had been previously rejected
- Allowing new types on existing fields
- For example, allowing passing
nullto unset a field such asuser.profile.displayName
- For example, allowing passing
Error handling
- Changing the string content of friendly error descriptions
- For example, changing the message in the error
title, or equivalent. Automated error handling behavior should use the error'scode, not its friendly description
- For example, changing the message in the error
- Changing the validation precedence of invalid HTTP requests
- For example, when sending a request that is both malformed and with invalid auth credentials, we may return either a status code of 400 or 401
- Promoting unclassified errors into categorized errors
- For example, for scenarios that return an error
codeofunhandled_errororuncategorized_error, the error may be changed to a more specific code instead
- For example, for scenarios that return an error
- Introducing new classifications of errors
- For example, in the error
codeor equivalent. Your code should be able to gracefully handle unknown errorcodevalues
- For example, in the error
- Changing the HTTP status code of unhandled API errors
- For example, changing
500 Internal Server Errorto something more specific like400 Bad Requestor401 Unauthorized
- For example, changing
Upgrade guides
The guides below outline the breaking changes to be aware of when upgrading versions of the API.
Upgrading from v1.1 to v2
The v2 API is a new set of APIs with extended capabilities to the v1 suite. Many of the existing v1 API endpoints have equivalent v2 API endpoints, however many request and response payloads have been significantly modified in the new API. A summary of the biggest differences is provided below. For more details, consult the documentation of each specific endpoint.
The v2 API was released on 2020-10-01 and includes the following changes from the v1.1 API:
General changes
- The
_idfield has been renamed toid - JWT scope of
appUseris no longer supported for server-to-server calls - Support for implicit app ids in request paths (for example,
/v1.1/appusers/{id}) has been removed. All app resources are now only accessible with paths including the app id (/v2/apps/:appId/…) - Standardized dates and timestamps on various objects into a single common format. All date-related fields should now be returned as strings with the format
YYYY-MM-DDThh:mm:ss.SSSZ - When the API returns an error, it now provides an
errorsarray in the response instead of anerrorobject - Offset-based pagination has been replaced by cursor-based pagination for all endpoints that support pagination
- Calls to modify a resource now use the
PATCHHTTP verb instead ofPUT. The behavior remains unchanged betweenPUTandPATCH
Apps
- The
metadatafield now allows partial updates. Values withinmetadatacan now be unset withnull - The List Apps API now uses cursor-based pagination instead of offset-based pagination
- The
serviceAccountIdquery parameter used to return only the apps that the service account has access to was replaced byfilter[serviceAccountId]
App Keys
- The Get App JWT API has been removed
Attachments
- Instead of passing an
appUserIdor auserIdin the query parameters it is now replaced withconversationId mediaUrlandmediaTypein the response body have been moved under a top-level objectattachmentto match the style of other API responses
Clients
- The List Clients API now uses cursor-based pagination instead of offset-based pagination
Conversations
- Conversation-related APIs are now pathed under
/conversationsinstead of/appusers, and a conversation id must be supplied instead of a user id - Added support for multiple conversations per user, including new endpoints to create, list and delete conversations for a user
- The concept of participant has been introduced to track a user's membership in a conversation, and which of a user's clients have been subscribed to receive messages in that conversation
- Added support for conversations between multiple users, including new endpoints to create, list and delete participants for a conversation
- The message schema has changed significantly when creating and retrieving messages. The previous message structure has been re-organized and composed into multiple top-level objects including
author,source, andcontent. See the message schema changes below for more details - The Post Message API now returns an array of
messagesrather than a singlemessageobject and an array ofextraMessages - The List Messages and Post Message APIs no longer return a
conversationobject - Post Activity API now requires an
authorobject in the body, rather than the previousrolefield - The Reset Unread Count API has been removed in favor of Post Activity API with
"author.role": "user" - Updated validation on certain fields when posting messages
- The
actionsarray now has has a max size of 10, and a minimum size of 1. The field remains optional if no actions are desired for the message mediaTypecan no longer be specified when posting a message. The type of the file will always be inferred from themediaUrl- Extra channel options
webview_height_ratioandfallback_urlare no longer considered forwebviewin Facebook Messenger. Use thesizeandfallbackproperties of the webview action instead - When specifying a
destination, integration typesapnandfcmhave been replaced byiosandandroid, respectively - Shorthand syntax will only be parsed in
texttype messages. Syntax passed in thetextfield of other message types will be ignored - A more specific
invalidFileerror will replace the genericbadRequesterror when invalid media is sent
- The
- The List Conversations API now uses cursor-based pagination instead of offset-based pagination
Deployments
Removed in v2
Integrations
- Integrations of type
fcmhave been replaced by theandroidtype. ThesenderIdandserverKeyproperties are no longer required when creating anandroidintegration - Integrations of type
apnhave been replaced by theiostype. Thecertificateproperty is no longer required when creating aniosintegration - The new integration type
customhas been introduced to replace the functionality of the previous webhooks API suite. All existing webhooks have been automatically upgraded to belong to custom integrations in the API - The Create Integration API now supports creating multiple instances of a channel (including all SDKs and third-party channels)
- When creating or updating an integration, the
displayNameproperty (if passed) now has a minimum length of 1 - The
signingKeyis now required when creating an integration of typemessagebird - The List Integrations API now uses cursor-based pagination instead of offset-based pagination
- The
typesquery parameter used to return only integrations of a specific type was replaced byfilter[types]
Messages
- The List Messages API now follows the v2 style for cursor-based pagination input and output parameters
- The List Messages API now uses message IDs instead of timestamps as the pagination cursor
Notifications
Not migrated to v2 yet
Persistent Menus
Removed in v2
Service Accounts
Removed in v2
Templates
Not migrated to v2 yet
Users
- The concept of
appUserhas been renamed touserin all API paths and request/response bodies - Clients of type
android,iosandwebare now unified under a single client with typesdk. Existing clients have been converted todevices - Introduced the concept of
devicesto replace the per-device tracking of metadata and push notification tokens that used to be handled by SDK clients - The
/channelsAPIs have been removed in favor of Create/List/Remove Client APIs - The List Clients API must now be used to fetch the list of clients for a given user, and includes both linked clients and pending clients
- The DELETE
/profileendpoint has been renamed to DELETE/personalinformation - The
metadatafield now allows unsetting all its values at once withnull - Updated validation on certain fields when creating / updating users:
- The
externalId,givenName,surname,email,avatarUrlandsignedUpAtfields are validated in regards to their type and length
- The
Webhooks
- Webhooks are now a sub-property of a new integration type
custom. Existing webhooks have been automatically upgraded to belong to custom integrations in the API - Integrations of type
customcan be created with the Create Integration API, and require awebhooksarray to be passed in the request. Once the custom integration is created, webhooks can be modified with the Update Webhook API - Every webhook will be assigned a unique
iddifferent from the custom integrationid, which can be used to update the webhook
Schema changes
App
- The
namefield has been renamed todisplayName - Removed
appTokenfield
App Key
- The
namefield has been renamed todisplayName
Client
platformhas been renamed totype- A new
statusofpendinghas been introduced to distinguish clients that have not been confirmed yet (previously calledpendingClients) - Removed fields
blockedandactivewhich were marked as deprecated in v1.1. Usestatusinstead - Removed fields
id,deviceId,pushNotificationTokenandappVersion. These are now properties of the device schema - The
primaryproperty is removed. To know the primary client of a user in relation to a conversation, use the List Participants API. The first item of a participant'sclientAssociationsarray represents the primary client
Conversation
- Added a new
typefield. Possible values arepersonalandsdkGroup - Removed fields
unreadCountandlastRead. Use the equivalent fields of each participant instead - Introduced new properties
metadata,lastUpdatedAt,displayNameanddescription appMakerLastReadis now a stringified date instead of a unix timestampappMakerLastReadproperty was renamed tobusinessLastRead
Custom Integration Key
- Change
nameproperty todisplayName
Destination
typehas been renamed tointegrationType- Payloads with a
destinationobject must include eitherintegrationIdorintegrationType, not both
Device
- Added device schema
Errors
descriptionhas been renamed totitle
Integration
- Introduced new types
ios,android, andcustom - Removed
apnandfcmas supported types, they are now exposed asiosandandroid
Message
messageSchemafield has been renamed toschemareceivedis now a stringified date instead of a unix timestampauthorIdhas been renamed touserIdand is no longer returned forbusinessmessagesappUserrole has been renamed touserappMakerrole has been renamed tobusiness- Removed
emailfield when posting a message. UseavatarUrlinstead - The previous message structure has been re-organized and composed into multiple top-level objects
- A new
authorobject has been introduced replacing the top-level propertiesrole,subroles,name,authorIdandavatarUrl. See the Messages section of the v2 API spec for more details id,received,source,destination,metadata,deleted,override,schema, andquotedMessageremain at the root of the message object- Most other fields have been moved under a
contentobject
- A new
- The values
apiandnotificationsfor a message'ssource.typehave been changed toapi:conversationsandapi:notificationsrespectively - Sub-objects within
contentno longer include an_id(i.e.actionsoritems)
Participant
- Added participant schema
Source
- New fields
clientanddevicemay now be included in webhook payloads whenincludeFullSourceis enabled for the webhook originalMessageTimestampis now a stringified date instead of a unix timestamp
User
userIdhas been renamed toexternalIdpropertieshas been renamed tometadata- Removed top-level fields
clientsandpendingClients. Use the List Clients API instead - Removed
conversationStartedfield - Removed
credentialRequiredfield - The user will now contain a
profilesub-object that holds thegivenName,surname,avatarUrl, andemailproperties
Webhook
- No longer an app-level concept. Webhooks are now a sub-property of integrations of type
custom, or integrations created by OAuth partners versioncan have a new valuev2includeFullAppUserhas been renamed toincludeFullUserincludeClienthas been renamed toincludeFullSource- Removed support for the wildcard trigger (
*). Triggers must all be individually selected - Updated the schema of all the existing webhooks to include an array of
eventsinstead of a single event. See the Webhook Payloads of the v2 API spec for more details - Reorganized and renamed the available triggers. Note that v1 webhooks can still be used in combination with the v2 API/webhooks if you need a trigger that has not yet been migrated
| v1.x trigger | Equivalent v2 trigger | Notes |
|---|---|---|
appUser:delete | user:remove | |
client:add | client:add | This event is now triggered for the following reasons: upon initiating a channel link, when logging in the sdk for the first time and when initiating an SDK device with an authCode. |
client:block | client:update | The payload will include a reason with the value blocked. |
client:remove | client:remove | The payload now includes the conversation whenever it is available. |
conversation:read | conversation:read | |
conversation:referral | conversation:referral | Triggered in the same cases as v1.x conversation:referral and conversation:start events, except when conversation:create is triggered instead. |
conversation:start | conversation:create | Now triggers when a conversation is created for any reason, not just in response to a start conversation event. The creationReason may be used to determine why the conversation was created. |
link:failure | client:remove | The payload will include a reason with either linkCancelled or linkFailure. |
link:match | client:update | The payload will include a reason field with the value matched. |
link:success | client:update | The payload will include a reason field with the value confirmed. |
merge:appUser | user:merge | |
message:appMaker | conversation:message | Subscribes to both user and business messages. |
message:appUser | conversation:message | Subscribes to both user and business messages. |
message:delivery:channel | conversation:message:delivery:channel | |
message:delivery:failure | conversation:message:delivery:failure | |
message:delivery:user | conversation:message:delivery:user | |
notification:delivery:channel | N/A | Not migrated to v2 yet. |
notification:delivery:failure | N/A | Not migrated to v2 yet. |
notification:delivery:user | N/A | Not migrated to v2 yet. |
passthrough:apple:extension | passthrough:apple:extension | |
passthrough:apple:interactive | passthrough:apple:interactive | |
postback | conversation:postback | The message and action linked to a postback event are no longer included in the webhook payload. |
request:failure | N/A | Not migrated to v2 yet. |
request:success | N/A | Not migrated to v2 yet. |
typing:appUser | conversation:typing |
Upgrading from v1 to v1.1
The v1.1 API was released on 2018-10-02 and includes the following changes from the v1 API:
Schema changes
Webhooks
- Webhooks include a
versionproperty - Removed support for
messagetrigger. Usemessage:appUserandmessage:appMakerinstead triggersis now a required property when creating a webhookmessage:appUserevents supportfilemessages. Previous versions sent them astextmessagespostback,conversation:start,message:appUserandmessage:appMakerevents now include truncated appUser schema- New message delivery webhooks have been introduced, described below. See the delivery events guide for more details:
- Removed
delivery:successanddelivery:failurewebhook triggers which are replaced bymessage:delivery:channelandmessage:delivery:failurerespectively message:delivery:channeltriggers when messages are delivered to SDKs.message:delivery:failurecan be triggered after amessage:delivery:channelevent if a message cannot be delivered to the user.message:delivery:useris a new trigger that allows to confirm the delivery of a message to a user for channels that support it.- The payloads used to include a list of
messages. They now only include onemessageand only contain an_idproperty. - New properties
isFinalEventandexternalMessagesare included in these new webhook payloads.
- Removed
AppUsers
- API responses no longer include a
devicesarray and acredentialRequiredproperty.deviceshas been renamed toclientslong ago and it was kept in API responses for backwards compatibility only - The Link App User To Channel API now requires a
confirmationproperty, and no longer accepts askipConfirmationproperty - The Pre-Create App User API no longer accepts a
credentialRequiredproperty
Conversations
typeis now a required property when posting a message
Upgrading webhooks without downtime
To avoid missing messages for apps used in production, the following strategy can be used to upgrade your webhook version without downtime:
- Modify your code to support the webhook schema changes mentioned above. You can use the
versionproperty included in all event payloads to conditionally execute code based on the webhook version. Your code should be capable of receiving both webhook versions, while ignoring the newer version for now. - Once changes from step (1) are deployed, create a custom integration with the new version with the equivalent triggers as the webhook you wish to upgrade.
- With both webhooks running, write and deploy code to accept payloads with the new version and ignore those with the old version.
- Once you are satisfied with the webhook upgrade, remove the webhook with the old version.
- At this point you may remove code specific to the old version.
Steps 2-5 should be tested in a non-production environment before they are applied to your production environment.