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
location
or a new integration type oftwitter
. For any code that processes entities with atype
property (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:read
webhooks 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.id
orkey.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
null
to 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
code
ofunhandled_error
oruncategorized_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
code
or equivalent. Your code should be able to gracefully handle unknown errorcode
values
- For example, in the error
- Changing the HTTP status code of unhandled API errors
- For example, changing
500 Internal Server Error
to something more specific like400 Bad Request
or401 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
_id
field has been renamed toid
- JWT scope of
appUser
is 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
errors
array in the response instead of anerror
object - Offset-based pagination has been replaced by cursor-based pagination for all endpoints that support pagination
- Calls to modify a resource now use the
PATCH
HTTP verb instead ofPUT
. The behavior remains unchanged betweenPUT
andPATCH
Apps
- The
metadata
field now allows partial updates. Values withinmetadata
can now be unset withnull
- The List Apps API now uses cursor-based pagination instead of offset-based pagination
- The
serviceAccountId
query 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
appUserId
or auserId
in the query parameters it is now replaced withconversationId
mediaUrl
andmediaType
in the response body have been moved under a top-level objectattachment
to 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
/conversations
instead 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
messages
rather than a singlemessage
object and an array ofextraMessages
- The List Messages and Post Message APIs no longer return a
conversation
object - Post Activity API now requires an
author
object in the body, rather than the previousrole
field - 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
actions
array 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 mediaType
can no longer be specified when posting a message. The type of the file will always be inferred from themediaUrl
- Extra channel options
webview_height_ratio
andfallback_url
are no longer considered forwebview
in Facebook Messenger. Use thesize
andfallback
properties of the webview action instead - When specifying a
destination
, integration typesapn
andfcm
have been replaced byios
andandroid
, respectively - Shorthand syntax will only be parsed in
text
type messages. Syntax passed in thetext
field of other message types will be ignored - A more specific
invalidFile
error will replace the genericbadRequest
error 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
fcm
have been replaced by theandroid
type. ThesenderId
andserverKey
properties are no longer required when creating anandroid
integration - Integrations of type
apn
have been replaced by theios
type. Thecertificate
property is no longer required when creating anios
integration - The new integration type
custom
has 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
displayName
property (if passed) now has a minimum length of 1 - The
signingKey
is now required when creating an integration of typemessagebird
- The List Integrations API now uses cursor-based pagination instead of offset-based pagination
- The
types
query 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
appUser
has been renamed touser
in all API paths and request/response bodies - Clients of type
android
,ios
andweb
are now unified under a single client with typesdk
. Existing clients have been converted todevices
- Introduced the concept of
devices
to replace the per-device tracking of metadata and push notification tokens that used to be handled by SDK clients - The
/channels
APIs 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
/profile
endpoint has been renamed to DELETE/personalinformation
- The
metadata
field now allows unsetting all its values at once withnull
- Updated validation on certain fields when creating / updating users:
- The
externalId
,givenName
,surname
,email
,avatarUrl
andsignedUpAt
fields 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
custom
can be created with the Create Integration API, and require awebhooks
array 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
id
different from the custom integrationid
, which can be used to update the webhook
Schema changes
App
- The
name
field has been renamed todisplayName
- Removed
appToken
field
App Key
- The
name
field has been renamed todisplayName
Client
platform
has been renamed totype
- A new
status
ofpending
has been introduced to distinguish clients that have not been confirmed yet (previously calledpendingClients
) - Removed fields
blocked
andactive
which were marked as deprecated in v1.1. Usestatus
instead - Removed fields
id
,deviceId
,pushNotificationToken
andappVersion
. These are now properties of the device schema - The
primary
property 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'sclientAssociations
array represents the primary client
Conversation
- Added a new
type
field. Possible values arepersonal
andsdkGroup
- Removed fields
unreadCount
andlastRead
. Use the equivalent fields of each participant instead - Introduced new properties
metadata
,lastUpdatedAt
,displayName
anddescription
appMakerLastRead
is now a stringified date instead of a unix timestampappMakerLastRead
property was renamed tobusinessLastRead
Custom Integration Key
- Change
name
property todisplayName
Destination
type
has been renamed tointegrationType
- Payloads with a
destination
object must include eitherintegrationId
orintegrationType
, not both
Device
- Added device schema
Errors
description
has been renamed totitle
Integration
- Introduced new types
ios
,android
, andcustom
- Removed
apn
andfcm
as supported types, they are now exposed asios
andandroid
Message
messageSchema
field has been renamed toschema
received
is now a stringified date instead of a unix timestampauthorId
has been renamed touserId
and is no longer returned forbusiness
messagesappUser
role has been renamed touser
appMaker
role has been renamed tobusiness
- Removed
email
field when posting a message. UseavatarUrl
instead - The previous message structure has been re-organized and composed into multiple top-level objects
- A new
author
object has been introduced replacing the top-level propertiesrole
,subroles
,name
,authorId
andavatarUrl
. See the Messages section of the v2 API spec for more details id
,received
,source
,destination
,metadata
,deleted
,override
,schema
, andquotedMessage
remain at the root of the message object- Most other fields have been moved under a
content
object
- A new
- The values
api
andnotifications
for a message'ssource.type
have been changed toapi:conversations
andapi:notifications
respectively - Sub-objects within
content
no longer include an_id
(i.e.actions
oritems
)
Participant
- Added participant schema
Source
- New fields
client
anddevice
may now be included in webhook payloads whenincludeFullSource
is enabled for the webhook originalMessageTimestamp
is now a stringified date instead of a unix timestamp
User
userId
has been renamed toexternalId
properties
has been renamed tometadata
- Removed top-level fields
clients
andpendingClients
. Use the List Clients API instead - Removed
conversationStarted
field - Removed
credentialRequired
field - The user will now contain a
profile
sub-object that holds thegivenName
,surname
,avatarUrl
, andemail
properties
Webhook
- No longer an app-level concept. Webhooks are now a sub-property of integrations of type
custom
, or integrations created by OAuth partners version
can have a new valuev2
includeFullAppUser
has been renamed toincludeFullUser
includeClient
has 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
events
instead 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
version
property - Removed support for
message
trigger. Usemessage:appUser
andmessage:appMaker
instead triggers
is now a required property when creating a webhookmessage:appUser
events supportfile
messages. Previous versions sent them astext
messagespostback
,conversation:start
,message:appUser
andmessage:appMaker
events now include truncated appUser schema- New message delivery webhooks have been introduced, described below. See the delivery events guide for more details:
- Removed
delivery:success
anddelivery:failure
webhook triggers which are replaced bymessage:delivery:channel
andmessage:delivery:failure
respectively message:delivery:channel
triggers when messages are delivered to SDKs.message:delivery:failure
can be triggered after amessage:delivery:channel
event if a message cannot be delivered to the user.message:delivery:user
is 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 onemessage
and only contain an_id
property. - New properties
isFinalEvent
andexternalMessages
are included in these new webhook payloads.
- Removed
AppUsers
- API responses no longer include a
devices
array and acredentialRequired
property.devices
has been renamed toclients
long ago and it was kept in API responses for backwards compatibility only - The Link App User To Channel API now requires a
confirmation
property, and no longer accepts askipConfirmation
property - The Pre-Create App User API no longer accepts a
credentialRequired
property
Conversations
type
is 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
version
property 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.