> ## Documentation Index
> Fetch the complete documentation index at: https://docs.open.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Zendesk troubleshooting

> Debug Zendesk connection, webhook, ticket creation, agent reply sync, and article sync issues.

Before debugging, have this ready:

* Your Zendesk <Tooltip tip="The subdomain of your Zendesk account — the acme part of acme.zendesk.com.">subdomain</Tooltip> and the admin email used for the <Tooltip tip="A long-lived credential generated in Zendesk Admin Center's Zendesk API section. Bound to the user whose email you provide.">API token</Tooltip>.
* A specific <Tooltip tip="OpenCX's identifier for a single conversation thread. Visible in the Inbox URL and linked to the Zendesk ticket via external_id.">session ID</Tooltip> (from [Inbox](https://platform.open.cx/inbox)) or Zendesk ticket ID where the problem shows.
* The webhook URL shown in [Settings → Integrations](https://platform.open.cx/settings/integrations) → Zendesk.

<Tip>
  Re-run **Verify** in [Settings → Integrations](https://platform.open.cx/settings/integrations) → Zendesk as your first step. Most issues are credential or webhook related.
</Tip>

<Info>
  **Fastest path to root cause:** filter Zendesk tickets by the `opencx_channel_*`, `opencx_sentiment_*`, or `opencx_handedoff` tags to scope the issue, then click **View session in OpenCX** in the first comment of the failing ticket. That link opens the full AI reasoning, tool calls, and handoff event — far faster than log-diving.
</Info>

## Common scenarios

Jump to the symptom that matches what you're seeing.

### **"Failed to verify credentials" on save**

<Tooltip tip="Usually caused by including .zendesk.com in the subdomain field, a token the admin has already revoked, or a Zendesk plan without API access.">Likely cause</Tooltip>: wrong subdomain format, expired token, or API access disabled.

**Fix:** use just the subdomain part (`acme`, not `acme.zendesk.com`). Regenerate the token in [Zendesk Admin Center](https://admin.zendesk.com/apps/integrations/apis/zendesk-api). Confirm **Token access** is toggled on.

### **"Failed to verify credentials" on Sunshine Messaging save**

<Tooltip tip="The most common cause is using a Sunshine Integration key instead of an App key. Integration keys are scoped to a single Sunshine integration and will fail authentication against OpenCX.">Likely cause</Tooltip>: wrong key type (Integration key, not App key), or wrong App ID.

**Fix:** confirm the Key ID starts with `app_`. If it doesn't, delete the key and create a new one from the **Conversations API** section of Admin Center — not from inside a specific integration. Re-copy the App ID from the top of that same page.

### **Handoff runs but no ticket appears in Zendesk**

<Tooltip tip="Ticket creation requires a Zendesk user tied to the contact's email. If the contact has no email, or the API token lacks user creation permission, ticket creation silently fails.">Likely cause</Tooltip>: contact has no email, or the Zendesk user behind the API token lacks permission to create users and tickets.

**Fix:** confirm the OpenCX contact has an email. Confirm the token's Zendesk user is an <Tooltip tip="A Zendesk role with full permission to manage users, tickets, and webhooks. Required for OpenCX integration.">admin</Tooltip> or an agent with full access.

### **Agent public replies don't reach the contact**

<Tooltip tip="Usually the Zendesk trigger isn't firing, or the webhook endpoint is wrong. Check Zendesk's webhook activity log first.">Likely cause</Tooltip>: webhook missing, trigger misconfigured, or wrong event subscription.

**Fix:** in [Zendesk Admin Center → Triggers](https://admin.zendesk.com/objects-rules/rules/triggers), confirm the condition is `Ticket is Updated` with a public comment present, and the action posts to the OpenCX webhook URL. <Tooltip tip="Zendesk's per-webhook activity log. Shows every delivery attempt, HTTP status, and payload. Essential for debugging missed deliveries.">Retry the failed delivery</Tooltip> from the webhook's activity log.

### **Internal notes reaching the contact**

<Tooltip tip="The trigger's JSON body is sending {{ticket.latest_comment}} — which includes internal notes — instead of {{ticket.latest_public_comment}}.">Likely cause</Tooltip>: trigger payload uses the wrong comment variable.

**Fix:** update the trigger to use <Tooltip tip="The Zendesk placeholder that expands only to the latest public comment on the ticket. Excludes internal notes.">`{{ticket.latest_public_comment}}`</Tooltip> specifically, not `{{ticket.latest_comment}}`.

### **Duplicate tickets for the same conversation**

<Tooltip tip="Handoff firing more than once before the first ticket links to the session via external_id. OpenCX deduplicates by external_id, so once the link exists, further events append instead of creating new tickets.">Likely cause</Tooltip>: handoff fires multiple times before the first ticket's <Tooltip tip="A Zendesk field that stores your own reference ID on a ticket. OpenCX writes the session ID here so future events match back to the same conversation.">`external_id`</Tooltip> links to the session.

**Fix:** none on your side — dedup is automatic once the link exists. If you see this consistently, open a support request with two example session IDs.

### **AI fields show blank on the ticket**

<Tooltip tip="The field mapping is disabled, the Zendesk field isn't a custom field, or the AI description is too vague for the AI to commit to a value.">Likely cause</Tooltip>: mapping disabled or description too vague.

**Fix:** check [Settings → Ticketing](https://platform.open.cx/settings/ticketing) → Zendesk AI Fields. Enable the mapping. Tighten the description with <Tooltip tip="A short, concrete description of what the field represents and how to pick a value. Vague descriptions ('customer feedback') produce vague or empty values.">concrete examples</Tooltip>.

### **Help Center articles not appearing in AI answers**

<Tooltip tip="Either the initial sync hasn't finished yet, or the articles are tagged internal — which restricts them to agent-facing surfaces like Assist Mode, not customer replies.">Likely cause</Tooltip>: initial sync still running, or articles are <Tooltip tip="Articles restricted to specific Zendesk user segments or still in draft. Tagged internal by OpenCX — usable by Assist Mode but not shown in customer-facing replies.">internal</Tooltip>.

**Fix:** open [Data Sources](https://platform.open.cx/data-sources), wait for sync to complete. Check article visibility in Zendesk — published + no segment restriction is required for public answers.

### **Webhook returns 4xx in Zendesk's activity log**

<Tooltip tip="A 4xx means OpenCX rejected the request. The webhook URL is probably stale — most commonly because you disconnected and reconnected without re-copying the URL into Zendesk.">Likely cause</Tooltip>: webhook URL is stale.

**Fix:** copy the current URL from [Settings → Integrations](https://platform.open.cx/settings/integrations) → Zendesk and update the webhook endpoint in Zendesk.

### **Webhook returns 5xx in Zendesk's activity log**

<Tooltip tip="A 5xx means OpenCX received the webhook but failed to process it. Usually because the payload doesn't include the external_id or ticket_id OpenCX needs to match back to a session.">Likely cause</Tooltip>: payload missing `ticket_id` or `external_id`.

**Fix:** update the trigger's JSON body to include `{{ticket.id}}` and `{{ticket.external_id}}`. See the [Ticketing API setup](/integrations/zendesk/ticketing-api) reference payload.

## Handoff creates a ticket but agent replies do nothing

Work through this checklist:

1. Open the ticket in Zendesk. Confirm it has tag <Tooltip tip="The tag OpenCX applies to every ticket it creates or writes to. Its absence means OpenCX never touched the ticket.">`opencx`</Tooltip> and an `external_id` set.
2. In [Zendesk Admin Center → Webhooks](https://admin.zendesk.com/apps/integrations/webhooks), open your OpenCX webhook. Check **Activity** — recent calls should return `2xx`. A `4xx` means the webhook URL is stale (re-copy from OpenCX). A `5xx` means OpenCX couldn't match the ticket to a session.
3. Confirm the <Tooltip tip="The Zendesk automation you created during setup. Must be active and firing on ticket updates with a public comment condition.">trigger</Tooltip> in [Admin Center → Triggers](https://admin.zendesk.com/objects-rules/rules/triggers) is active.
4. Confirm the reply was posted as **Public reply**, not **Internal note**.
5. Confirm the original contact channel is still reachable (email address valid, WhatsApp/SMS number still subscribed).

## Assist Mode doesn't post suggestions

<Warning>
  **Assist Mode is a discouraged fallback.** We recommend [autopilot](/handoff/introduction) for every new deployment — Assist exists only for teams that aren't yet ready to hand customer replies to the AI. If you're evaluating OpenCX, start with autopilot.
</Warning>

If you're already running Assist and suggestions aren't appearing, check in order:

* The ticket wasn't created by OpenCX — <Tooltip tip="Assist only runs on tickets your reps opened. Tickets OpenCX created on handoff use autopilot instead.">Assist runs on rep-opened tickets only</Tooltip>.
* The ticket's topic isn't on the <Tooltip tip="A list of topics you've excluded from Assist in Autopilot settings. Tickets matching these topics are tagged with opencx_skipped_assist_mode_because_of_the_topic_in_no_assist_list.">no-assist list</Tooltip> (look for that tag).
* The AI produced an answer — look for `opencx_skipped_not_helpful_answer`, which means the AI judged its own answer incomplete and stayed quiet.
* The ticket is in a status where suggestions apply (open / pending).

<AccordionGroup>
  <Accordion title="How to enable Assist (if you must)" icon="gear">
    Assist runs on the same webhook and trigger as [Ticketing API](/integrations/zendesk/ticketing-api) — no extra credentials.

    1. Complete Ticketing API setup first.
    2. In [Settings → Autopilot](https://platform.open.cx/settings/autopilot), configure the no-assist topic list.
    3. In [Settings → Integrations](https://platform.open.cx/settings/integrations) → Zendesk Ticketing, toggle **Assist Mode** on.

    Assist posts drafts as internal notes on rep-owned tickets. Tag `opencx_assist_mode` is applied to every ticket Assist writes to. The customer never sees the draft.
  </Accordion>
</AccordionGroup>

## Messaging (Sunshine) issues

### **Handoff on WhatsApp creates a ticket instead of a chat**

<Tooltip tip="Sunshine Conversations credentials aren't saved, or the Messaging tab in Settings → Integrations doesn't show Active. Without Sunshine, OpenCX falls back to creating a Zendesk ticket for the handoff.">Likely cause</Tooltip>: Sunshine credentials missing or inactive.

**Fix:** confirm the Messaging tab in [Settings → Integrations](https://platform.open.cx/settings/integrations) → Zendesk shows **Active**. Re-enter credentials if needed.

### **Rep reply in Agent Workspace doesn't reach WhatsApp**

<Tooltip tip="The Sunshine webhook isn't registered, or it's subscribed to the wrong events. OpenCX needs conversation:message at minimum.">Likely cause</Tooltip>: webhook not registered or wrong event subscription.

**Fix:** re-register the Sunshine webhook subscribed to `conversation:message`. See [Sunshine Conversations setup](/integrations/zendesk/sunshine-conversations).

### **Second chat session from the same end user never reaches Agent Workspace**

<Tooltip tip="Sunshine's default 'personal' conversation mode allows only one open conversation per end user. OpenCX creates a new Sunshine conversation per chat session, so the second POST /v2/apps/{appId}/conversations for the same user fails and the handoff silently never lands in Zendesk.">Likely cause</Tooltip>: multi-conversations not enabled on the Sunshine app.

**Fix:** turn on multi-conversations in [Admin Center → Channels → Messaging and social → Messaging → Manage settings → Multi-conversations](https://admin.zendesk.com/channels/messaging_and_social/messaging) for every Web/iOS/Android channel OpenCX answers on. Full walkthrough in the Sunshine setup — see [Turn on multi-conversations for the Sunshine app](/integrations/zendesk/sunshine-conversations#turn-on-multi-conversations-for-the-sunshine-app). Note this change is irreversible.

### **Sunshine conversation never appears as a Zendesk ticket**

<Tooltip tip="Without AI agent tickets, Zendesk only creates a ticket for a messaging conversation when it's escalated to a human agent. With it, AI-only conversations surface as read-only tickets from the first message.">Likely cause</Tooltip>: working as designed — Sunshine conversations only surface as tickets after handoff to a human, unless **AI agent tickets** is turned on.

**Fix:** if you want to see AI-only conversations as tickets in the Agent Workspace before escalation, turn on **AI agent tickets** in [Admin Center → Channels → Messaging and social → Messaging → Manage settings → AI agent conversations as tickets in Agent Workspace](https://admin.zendesk.com/channels/messaging_and_social/messaging). These tickets are read-only until handoff. Zendesk turned this on by default for all accounts on **May 4, 2026**, but accounts using Zendesk's **AI agents - Advanced** add-on are exempt and may still have it off. Full reference: [Understanding AI agent tickets for AI agent–only conversations](https://support.zendesk.com/hc/en-us/articles/9204149016346-Understanding-AI-agent-tickets-for-AI-agent-only-conversations).

### **Session shows no Zendesk ticket id in the OpenCX Inbox**

<Tooltip tip="OpenCX stamps the Zendesk ticket id on a session via the opencx-messaging-ticket-link event webhook, which fires on every message added to a Zendesk messaging ticket. If no ticket exists for the conversation — the default for AI-only conversations when AI agent tickets is off — there is nothing to link.">Likely cause</Tooltip>: no Zendesk ticket exists for the conversation yet, or the `opencx-messaging-ticket-link` event webhook is missing.

Work through this checklist:

1. **Was the conversation handed off?** If not, and **AI agent tickets** is off in Zendesk, no ticket exists — an empty ticket id is expected, not a bug. The id appears within seconds of handoff. To get ticket ids for AI-only conversations too, turn on **AI agent tickets** — see [Turn on AI agent tickets if you want ticket ids before handoff](/integrations/zendesk/sunshine-conversations#turn-on-ai-agent-tickets-if-you-want-ticket-ids-before-handoff).
2. **Does the event webhook exist?** In [Admin Center → Apps and integrations → Webhooks](https://admin.zendesk.com/apps/integrations/webhooks), look for an active webhook named `opencx-messaging-ticket-link` subscribed to [`messaging_ticket.message_added`](https://developer.zendesk.com/api-reference/webhooks/event-types/messaging-events/). If it's missing, re-save your Zendesk Messaging settings in [Settings → Integrations](https://platform.open.cx/settings/integrations) — OpenCX provisions it automatically on save, provided the **Zendesk API credentials** panel is filled in.
3. **Did the session predate the webhook?** Linking is forward-only: sessions that ended before the webhook was provisioned keep an empty ticket id. There is no retroactive backfill.

### **AI doesn't take the conversation back after a ticket is solved or closed**

<Tooltip tip="Two separate things must be true for AI handback to work: (1) Zendesk must release Sunshine switchboard control, which only happens on Solved→Closed transition (default 4-day automation gap); (2) the account-wide Sunshine Conversation control must be 'Release control', otherwise handback walks the next-integration chain and lands on whatever zd-agentWorkspace points at (typically zd-answerBot), not OpenCX.">Likely cause</Tooltip>: one of two routing-config gaps — either the Solved→Closed transition hasn't fired yet, or the account's `Conversation control` setting isn't `Release control` so handback follows the wrong chain.

**Fix #1 — Set the account-wide Sunshine `Conversation control` to `Release control`. This is almost always the actual fix.**

`Conversation control` is an **account-wide Sunshine Conversations switchboard setting** — not a per-bot setting. It lives on the Messaging setup page, not inside the OpenCX marketplace bot entry.

In Zendesk Admin Center, go to **Channels → Messaging and social → Messaging**, open your messaging configuration (`https://<your-subdomain>.zendesk.com/admin/channels/messaging_and_social/messaging/setup`), expand the **Conversation control** section, select **Release control**, and save.

Why this matters: with the default `Pass control`, when an agent closes a ticket Sunshine `passControl`'s the conversation to whatever `nextSwitchboardIntegrationId` is wired on the Agent Workspace integration — typically Zendesk's own `zd-answerBot`, not OpenCX. With `Release control`, Sunshine clears the active integration on close, and the customer's next message gets re-assigned via the per-channel `defaultResponder` (which is OpenCX once configured per setup step 7).

References:

* Zendesk's [About Sunshine Conversations in Zendesk Suite](https://support.zendesk.com/hc/en-us/articles/5514406080538) — section *"Configuring conversational control"*.
* Zendesk's [Setting an advanced AI agent as the default responder for a messaging channel](https://support.zendesk.com/hc/en-us/articles/8357757911834-Setting-an-advanced-AI-agent-as-the-default-responder-for-a-messaging-channel) — search the article for *"Release control"*.

**Fix #2 — Make sure OpenCX is the per-channel default responder.**

Even with `Release control`, the post-handback routing only lands on OpenCX if the channel itself has OpenCX as its default responder. In Admin Center → **AI → AI agents → AI agents → Marketplace bots → OpenCX**, under **Channels**, click **Options → Assign default** for every channel you want AI on (or use **Set as default for all channels** to cover the lot). Reference: [Managing third-party bots in Admin Center](https://support.zendesk.com/hc/en-us/articles/5064149334426-Managing-third-party-bots-in-Admin-Center).

**Fix #3 — Shorten the Solved→Closed window so handback fires quickly, not in 4 days.**

Sunshine only hands control back on the **Closed** transition, not on **Solved**. By default Zendesk waits 4 days. Until then, any return message sticks with Agent Workspace.

* **Quick option:** edit the built-in automation `Close ticket 4 days after status is set to solved` in [**Admin Center → Objects and rules → Business rules → Automations**](https://admin.zendesk.com/objects-rules/rules/automations) and drop the timeframe (down to 1 hour).
* **Immediate option:** add a Zendesk trigger that closes any ticket whose status changes to Solved, so handback fires the instant an agent solves.

Reference: [Managing conversation handoff and handback](https://support.zendesk.com/hc/en-us/articles/4408824482586-Managing-conversation-handoff-and-handback) — section *"Modifying the time between the solved and closed states"*.

**Verify after the changes:** solve and close a test ticket, send a follow-up message from the same end user, and confirm the next inbound webhook arrives with `activeSwitchboardIntegration.name = opencx` (visible in the Zendesk webhook activity log or the OpenCX session timeline). If `activeSwitchboardIntegration.name` is still `zd-answerBot` or `zd-agentWorkspace`, fix #1 hasn't been applied.

### **Duplicate contact in Zendesk for the same WhatsApp number**

<Tooltip tip="Sunshine uses a separate identity model from Zendesk's support API. Without the Zendesk API token configured alongside Sunshine, OpenCX cannot merge the Sunshine messaging contact with the matching Zendesk support user — resulting in two user records.">Likely cause</Tooltip>: <Tooltip tip="The process of linking a Sunshine messaging contact to an existing Zendesk support user by email. Requires a Zendesk API token on the Messaging integration.">user merge</Tooltip> skipped because the Zendesk API credentials are missing from the Messaging integration.

**Fix:** paste the same credentials you use for Ticketing into the **Zendesk API credentials** panel under the Messaging setup.

## Limits & timing

|                                                              | Value                                                |
| ------------------------------------------------------------ | ---------------------------------------------------- |
| **Webhook processing timeout**                               | 10 seconds                                           |
| **Deduplication window** (agent replies, Assist suggestions) | 48 hours                                             |
| **Help Center initial sync**                                 | Minutes to a few hours depending on article count    |
| **Help Center incremental sync**                             | Hourly / daily (configurable per source)             |
| **Zendesk API rate limit**                                   | Governed by your Zendesk plan (200 req/min standard) |

<Note>
  OpenCX retries on transient Zendesk failures but does not indefinitely retry past rate limits. Heavy backfills during peak hours can slow down. Run them overnight when possible.
</Note>

***

## Related Documentation

<CardGroup cols={2}>
  <Card title="Ticketing API" icon="envelope" href="/integrations/zendesk/ticketing-api">
    Re-verify email handoff credentials and webhook setup.
  </Card>

  <Card title="Sunshine Conversations" icon="messages" href="/integrations/zendesk/sunshine-conversations">
    Re-verify chat, SMS, WhatsApp, and social setup.
  </Card>

  <Card title="Channels" icon="grid-2" href="/integrations/zendesk/channels/widget">
    Per-channel implementation details for Widget, WhatsApp, SMS, Phone, and Email.
  </Card>

  <Card title="Handoff settings" icon="user-group" href="/handoff/introduction">
    Global handoff rules and office hours.
  </Card>
</CardGroup>
