Audit chat agents on Zendesk Sunshine Conversations

Evidova reads the messages Zendesk sends as they land, and scores the conversation they belong to.

What it catches

Sunshine Conversations carries one conversation across every channel you have connected to it. It does not tell you whether the reply was right. Evidova reads both sides and scores the conversation against the checks you approved: whether the agent answered the question asked, whether it said it was not a person when asked, whether it promised something nobody authorised, and where the customer stopped replying.

Connect Zendesk

  1. In Evidova, open Setup, choose Zendesk, and save the connector so that it has a URL.
  2. Copy the URL we generate.
  3. Sunshine Conversations has no screen for this, and no way to ask it what has changed since last time, so the webhook is the only way in. Create it through the Sunshine API instead: POST to /v2/apps/{appId}/integrations/{integrationId}/webhooks with that URL as the target and conversation:message as the only trigger.
  4. The response carries a secret. Paste it back into the Evidova connector. Reading the same webhook again shows it a second time if you lose it.
https://app.evidova.com/ingest/webhooks/sunco/<your-token>
Zendesk does not sign what it sends, so the token in the path is what protects this URL. Treat it like a password: anyone who has it can post to your workspace. Rotate it from Setup if it leaks.

What we read from Zendesk

events[].typeWhich trigger fired. Only conversation:message is read
events[].payload.conversation.idThe conversation. It is what groups the messages, and there is no phone number or email in play
events[].payload.message.idWhich message this is. Required
events[].payload.message.receivedWhen Zendesk received it, to the millisecond
events[].payload.message.content.typeWhat shape the message is. text, image and file are read, and nothing else is
events[].payload.message.content.textWhat was said, which on an image or a file is whatever words came with it
events[].payload.message.author.typeWhich side sent it. business is your side, anything else is the customer
events[].payload.message.author.subtypes[]Whether a person, the platform or the bot sent it. agent is a person in the agent workspace, activity is the platform's own notice, and a business send with no marker at all is read as the bot
events[].payload.message.author.userId, .displayNameWho replied, when Zendesk marked the author as a person. A name with no id is kept on its own, because it is what the customer saw

What we ignore, and why

One delivery can carry several entries at once, and they can belong to different customers and different conversations, so each entry is read on its own and a bad entry costs only itself. An entry that is not a conversation:message is left out, because that is the only trigger this connector asks Zendesk for. A message whose content type is not text, image or file produces no turn either: those three are the shapes we can take words out of, and inventing words for the rest would put sentences in somebody's mouth.

One trap worth knowing

Zendesk does not sign these deliveries. The secret it shows you when the webhook is created is the same secret it sends back, unchanged, in the X-Api-Key header, so what reaches us is a shared password and not a signature over the body. Two things follow from that. Anyone holding both the URL and that secret can post whatever they like, so treat the pair the way you treat a password and create a new webhook to change it. And nothing ties the secret to the bytes, so a delivery somebody captured can be sent at us again; what stops it becoming a second turn is the message id, not the secret.

What Zendesk gives us

Channelchat
AudioNo
TimestampsMilliseconds, on Zendesk's clock
DeliveryWebhook, push
RetriesZendesk retries

Read next

This page as markdown