Connect Retool to Zendesk using a REST API Resource with your Zendesk subdomain as the base URL (https://yourcompany.zendesk.com/api/v2/) and API token authentication. Build support operations dashboards that search, create, and update tickets, manage agents and groups, and embed Retool apps as native sidebar apps inside Zendesk Support using the Zendesk Apps Framework.
| Fact | Value |
|---|---|
| Tool | Zendesk |
| Category | Communication |
| Method | REST API Resource |
| Difficulty | Intermediate |
| Time required | 25 minutes |
| Last updated | April 2026 |
Build a Zendesk Support Operations Panel in Retool
Zendesk is the backbone of many customer support operations, but its native reporting and workflow tools have limits. Support managers often need custom dashboards that combine Zendesk ticket data with internal databases, CRM records, or billing systems — something Zendesk's native views cannot do natively. Retool bridges this gap by connecting to Zendesk's comprehensive REST API and presenting data through fully customizable Tables, Charts, and Forms.
With a Retool-Zendesk integration, you can build an escalation dashboard that surfaces every ticket breaching its SLA, a bulk ticket update panel for triaging large queues, or an agent performance tracker that charts first-reply times by team. Because Retool queries run server-side through its proxy, you can safely store your Zendesk API token in configuration variables and combine Zendesk data with PostgreSQL order records or Stripe subscription data in the same interface.
An advanced use case unique to Zendesk is the ability to embed your Retool app directly inside the Zendesk Support ticket view as a sidebar app. Using the Zendesk Apps Framework (ZAF) and the ZAFClient JavaScript SDK, your Retool app can receive the current ticket ID from Zendesk and automatically pull related data from your internal systems — giving support agents a 360-degree customer view without leaving Zendesk.
Integration method
Zendesk does not have a native Retool connector, so you connect via a REST API Resource pointing to your subdomain's API endpoint (https://yourcompany.zendesk.com/api/v2/). Authentication uses Basic Auth with your agent email address and an API token generated from Zendesk's Admin Center. Once configured, all Retool queries route through Retool's server-side proxy, so credentials never reach the browser and CORS is not a concern.
Prerequisites
- A Zendesk account with Admin or Agent access (Admin required for API token generation)
- Your Zendesk subdomain (the prefix before .zendesk.com in your support URL)
- A Retool account with permission to create Resources
- Familiarity with Retool's Query Editor and Table component basics
- Understanding of HTTP Basic Auth (email/token format)
Step-by-step guide
Generate a Zendesk API token
Before configuring Retool, you need a Zendesk API token. Log in to Zendesk Support as an Admin and navigate to Admin Center — you can access it by clicking the gear icon in the left sidebar or visiting https://yoursubdomain.zendesk.com/admin. In Admin Center, expand the Apps and Integrations section in the left navigation, then click APIs → Zendesk API. On the API settings page, ensure the Token Access toggle is enabled (shown in green). Click the Add API token button to create a new token. Give it a descriptive name like 'Retool Integration' so you can identify it later. After saving, Zendesk displays the token exactly once — copy it immediately and store it securely. This token is used in combination with your admin email address for Basic Auth. The format Zendesk expects is: username = your_email/token (literally append /token to your email), and password = the token string itself. For example, if your email is ops@company.com, the username you configure in Retool will be ops@company.com/token.
Pro tip: Create a dedicated Zendesk admin account specifically for API integrations (e.g., retool-integration@company.com) rather than using a personal account. This prevents the integration from breaking if an employee leaves.
Expected result: You have a Zendesk API token copied and ready, and you know your subdomain (e.g., 'acme' from acme.zendesk.com).
Create the Zendesk REST API Resource in Retool
In Retool, click the Resources tab in the left sidebar (or navigate to your Retool instance's /resources path). Click the Add Resource button in the top right. From the resource type list, scroll to find REST API and click it. On the configuration screen, give the resource a clear name like 'Zendesk API'. In the Base URL field, enter your Zendesk API base URL in the format: https://yoursubdomain.zendesk.com/api/v2 — replace 'yoursubdomain' with your actual Zendesk subdomain. Do not include a trailing slash. Scroll down to the Authentication section and select Basic Auth from the dropdown. In the Username field, enter your admin email address followed by /token — for example: ops@company.com/token. In the Password field, enter the API token you copied in the previous step. Scroll to the Headers section and add a default header: set the key to Content-Type and the value to application/json. This ensures POST and PUT requests send JSON bodies correctly. Click Save Changes. Retool will validate the connection — if you see a green success indicator, the resource is ready. If you see an authentication error, double-check that the username includes the /token suffix and that the API token was not truncated when you copied it.
Pro tip: Store your API token in Retool's Configuration Variables (Settings → Configuration Variables) rather than directly in the resource. Reference it as {{ retoolContext.configVars.ZENDESK_API_TOKEN }} in the Password field for easier rotation.
Expected result: A Zendesk API resource appears in your Resources list with a green connection indicator.
Build a ticket search and list query
With the resource created, open or create a Retool app. In the app's Code panel (bottom panel), click the + button to create a new query. Select your Zendesk API resource. In the query editor, set the Method to GET. For the Path field, enter /tickets.json to retrieve the list of tickets. To search tickets, use the /search.json endpoint instead — set the path to /search.json and in the URL Parameters section, add a parameter with key 'query' and value such as {{ 'type:ticket status:open assignee_id:' + userSelect.value }}. This leverages Zendesk's powerful search API which supports a rich query language. Add a second URL parameter: key 'sort_by' with value 'updated_at', and a third: key 'sort_order' with value 'desc'. Add a fourth parameter: key 'per_page' with value {{ pagination.pageSize || 25 }}. In the Transformer section of the query (click the Advanced tab), enable the transformer toggle and write a JavaScript transformer to reshape the response. The search endpoint returns results in a 'results' array, while the tickets endpoint returns them in a 'tickets' array. Your transformer should normalize this. Name the query 'getTickets' and set it to run when the app loads by toggling 'Run query when app loads' in the query settings.
1// Transformer for Zendesk ticket list2const tickets = data.results || data.tickets || [];3return tickets.map(ticket => ({4 id: ticket.id,5 subject: ticket.subject,6 status: ticket.status,7 priority: ticket.priority || 'normal',8 requester_id: ticket.requester_id,9 assignee_id: ticket.assignee_id,10 created_at: new Date(ticket.created_at).toLocaleDateString(),11 updated_at: new Date(ticket.updated_at).toLocaleDateString(),12 url: `https://yoursubdomain.zendesk.com/agent/tickets/${ticket.id}`13}));Pro tip: Zendesk's search endpoint supports advanced queries like 'type:ticket status:open priority:urgent created>2024-01-01'. Build a Text Input component in Retool and bind its value to the search query parameter for real-time ticket filtering.
Expected result: The getTickets query returns an array of normalized ticket objects, visible in the query's Results panel.
Build the support operations dashboard UI
Now build the visual dashboard. From the component panel on the right side of the Retool editor, drag a Table component onto the canvas. In the Table's Data property (right panel), set the value to {{ getTickets.data }}. The table automatically creates columns from the transformer output keys. Configure the visible columns by clicking on the Table and using the Column Configuration section in the right panel — show: id, subject, status, priority, created_at, updated_at. Set the id column to render as a Link type, with the href set to {{ row.url }}, so agents can click directly to the Zendesk ticket. Add a row above the table with a Text Input component (name it 'searchInput') for search, two Select components for status and priority filters, and a Date Range Picker for created_at filtering. Add a Button labeled 'Search' that triggers the getTickets query on click. Below the table, add a Container with a Form for updating ticket status. Add a Text component displaying 'Update Ticket #{{ ticketsTable.selectedRow.id }}', a Select component with options ['open','pending','hold','solved'] for new status, a Multiline Text Input for an internal comment, and an Update button. Create a second query named 'updateTicket' — set Method to PUT, Path to /tickets/{{ ticketsTable.selectedRow.id }}.json, Body Type to JSON, and Body to: { "ticket": { "status": "{{ statusSelect.value }}", "comment": { "body": "{{ commentInput.value }}", "public": false } } }. In the updateTicket query's On Success handler, add two actions: 'Show notification' with message 'Ticket updated successfully', and 'Trigger query → getTickets' to refresh the list.
1{2 "method": "PUT",3 "path": "/tickets/{{ ticketsTable.selectedRow.id }}.json",4 "body": {5 "ticket": {6 "status": "{{ statusSelect.value }}",7 "comment": {8 "body": "{{ commentInput.value }}",9 "public": false10 }11 }12 }13}Pro tip: Add a Confirm Modal to the Update button's event handler before triggering the updateTicket query. This prevents accidental ticket status changes in production.
Expected result: A functional support dashboard shows a searchable, filterable ticket table with a detail panel for updating ticket status and adding internal comments.
Add escalation workflows and multi-resource data joining
To build an escalation workflow, create a new query named 'escalateTicket'. Set Method to PUT, Path to /tickets/{{ ticketsTable.selectedRow.id }}.json. In the Body, construct a JSON payload that reassigns the ticket to an escalation group and adds an urgent priority tag. First, you need your escalation group's ID — create a helper query named 'getGroups' with GET method and path /groups.json, then use its data to populate a Select component for group selection in your escalation form. For the escalation body, set priority to 'urgent', group_id to {{ groupSelect.value }}, and add a tag 'escalated' to the ticket's tags array. To enrich ticket data with information from your internal systems (a powerful multi-resource pattern), create another query named 'getCustomerData' that uses a different resource — for example, a PostgreSQL resource connected to your customer database. Write a query that joins ticket requester emails to customer records: SELECT c.id, c.plan, c.mrr, c.account_manager FROM customers c WHERE c.email = '{{ getTickets.data.find(t => t.id === ticketsTable.selectedRow.id)?.requester_email }}'. Display this customer context in a side panel next to the ticket detail area. This multi-resource pattern — Zendesk data enriched by internal database data — is one of Retool's most valuable capabilities for support operations teams. For complex integrations involving multiple Zendesk resources, custom transformers, and escalation Workflows, RapidDev's team can help architect and build your Retool support operations solution.
1// Transformer: merge Zendesk ticket data with internal customer records2const tickets = getTickets.data || [];3const customers = getCustomerData.data || [];45return tickets.map(ticket => {6 const customer = customers.find(c => c.requester_id === ticket.requester_id);7 return {8 ...ticket,9 customer_plan: customer?.plan || 'Unknown',10 customer_mrr: customer?.mrr ? `$${customer.mrr}` : 'N/A',11 account_manager: customer?.account_manager || 'Unassigned'12 };13});Pro tip: Use Retool Workflows to build scheduled escalation notifications — set up a Workflow that runs every 15 minutes, queries Zendesk for tickets with due_at timestamps in the past, and sends a Slack notification to the escalation channel with ticket details.
Expected result: Tickets in the dashboard display enriched customer context from your internal database, and the escalation workflow correctly reassigns and re-prioritizes selected tickets.
Embed the Retool app as a Zendesk sidebar app
Zendesk's Apps Framework (ZAF) allows you to embed external web content as sidebar apps that appear in the ticket view. To embed your Retool app, first publish it: click the Share button in the top-right of the Retool editor, configure access settings, and copy the published URL. Next, go to the Zendesk Marketplace developer portal (https://developer.zendesk.com/apps/framework/) and create a new private app. In the app's manifest.json, set the location to 'ticket_sidebar' and the URL to your published Retool app URL. To pass the current ticket ID from Zendesk to your Retool app, append a URL parameter: your-retool-url?ticket_id={{ticket.id}} using ZAF's template syntax. In your Retool app, add a URL Parameters data source — in the Code panel, create a query of type 'URL parameters' named 'urlParams'. Reference the ticket ID as {{ urlParams.data.ticket_id }} in your ticket-specific queries. This way, when an agent opens a Zendesk ticket, your Retool sidebar app automatically loads with the correct ticket's data. In the Zendesk Apps Framework configuration, you can also use the ZAF client JavaScript to read additional ticket context (requester email, organization ID) and pass them as URL parameters to your Retool app. Deploy the Zendesk app through the Zendesk Admin Center → Apps and Integrations → Private Apps to make it available to your support team.
1// ZAF client initialization in a Zendesk App manifest.json2// This goes in your Zendesk app's iframe, not in Retool directly3// Your Retool app URL receives the ticket_id via URL parameter45{6 "name": "Retool Customer Context",7 "author": {8 "name": "Your Company",9 "email": "ops@yourcompany.com"10 },11 "version": "1.0.0",12 "frameworkVersion": "2.0",13 "location": {14 "support": {15 "ticket_sidebar": {16 "url": "https://your-retool-app-url.retool.com/app/zendesk-context?ticket_id={{ticket.id}}&requester={{ticket.requester.email}}"17 }18 }19 }20}Pro tip: Set your Retool app's height in the Zendesk sidebar to at least 600px via the ZAF client's resize method. Sidebar apps default to a small height that may cut off your dashboard.
Expected result: Zendesk agents see your Retool app in the ticket sidebar, automatically showing customer context data that matches the open ticket without any manual searching.
Common use cases
Build a support escalation and SLA monitoring dashboard
Create a Retool panel that continuously queries Zendesk for open tickets approaching or breaching SLA. Display breach risk by priority, assigned group, and requester organization. Include one-click escalation buttons that reassign tickets and post internal notes, and show trend charts of SLA compliance over rolling 30-day periods.
Build a Retool dashboard showing all open Zendesk tickets with SLA_breach_at timestamps, filterable by priority, group, and assignee. Include a Chart of breach rate over time, a Table with inline status-update buttons, and a Form to add internal comments.
Copy this prompt to try it in Retool
Build an agent performance and queue analytics panel
Create a Retool analytics dashboard that aggregates Zendesk ticket data to show per-agent resolution times, first-reply performance, and open queue sizes. Use Charts for trending, Tables for per-agent breakdowns, and date range selectors to compare performance periods for support managers.
Build a Retool panel that queries Zendesk for all solved tickets in a date range, groups by assignee_id, and shows Charts for average handle time, first-reply time, and CSAT score per agent.
Copy this prompt to try it in Retool
Build an embedded customer context sidebar app for Zendesk Support
Create a Retool app that shows agent-facing customer data (orders, subscription status, past contacts) when they view a Zendesk ticket. Embed this Retool app as a Zendesk sidebar app using the ZAF SDK so agents see full customer context without leaving the Zendesk ticket view.
Build a Retool app that accepts a Zendesk ticket ID, looks up the requester's email in your PostgreSQL customer database, and displays their recent orders, subscription tier, and open issues in a compact sidebar layout.
Copy this prompt to try it in Retool
Troubleshooting
401 Unauthorized error when testing the Zendesk resource connection
Cause: The Basic Auth username must be in the format email/token (with a literal /token suffix), not just the email address. A missing /token suffix or incorrect API token causes authentication to fail.
Solution: In the Retool Resource settings, verify the Username field contains your email address followed literally by /token — for example, ops@company.com/token. Verify the Password field contains your Zendesk API token (not your Zendesk account password). Regenerate the API token in Zendesk Admin Center → Apps and Integrations → APIs if you are unsure it was copied correctly.
API returns results but data shape does not match — transformer throws 'Cannot read property of undefined'
Cause: The Zendesk search endpoint returns results in a 'results' array while the tickets list endpoint returns them in a 'tickets' array. If you switch between endpoints without updating the transformer, the array key reference breaks.
Solution: Use a safe fallback in your transformer: const tickets = data.results || data.tickets || []. This handles both endpoint response shapes. Also check for API errors by logging data.error in the transformer before processing.
1const tickets = data.results || data.tickets || [];2if (!Array.isArray(tickets)) {3 console.log('Unexpected response:', JSON.stringify(data));4 return [];5}6return tickets.map(ticket => ({7 id: ticket.id,8 subject: ticket.subject || '(no subject)',9 status: ticket.status10}));Zendesk rate limit errors — API responds with 429 Too Many Requests
Cause: Zendesk's API enforces rate limits of 700 requests per minute for most plans. Retool apps that run multiple queries simultaneously (e.g., separate queries for tickets, users, and groups on page load) can hit this limit, especially in apps viewed by many simultaneous users.
Solution: Consolidate data retrieval using Zendesk's search API which can return enriched ticket data in fewer requests. Use Retool's query caching (enable in the query's Advanced settings with a cache duration of 30-60 seconds) to avoid redundant API calls. For dashboards used by many users, consider building a Retool Workflow that fetches and caches data on a schedule into Retool Database, and have your app queries read from Retool Database instead of hitting Zendesk directly.
Sidebar app shows blank content or Retool app does not load inside Zendesk
Cause: Retool apps embedded in Zendesk sidebars may be blocked by the app's Content Security Policy (CSP) or the app is attempting to load an unpublished Retool URL.
Solution: Ensure you are using the published Retool app URL (not the editor URL). In Retool's Share settings, verify the app is published and the access level allows external embedding. In your Zendesk app's manifest.json, add the Retool domain to the allowed_domains list. Check that your Retool app does not use window.parent or other cross-origin JavaScript that would conflict with Zendesk's iframe sandboxing.
Best practices
- Use a dedicated Zendesk service account (e.g., retool@yourcompany.com) for API token generation, separate from personal accounts, so credential rotation does not depend on individual employees
- Store the Zendesk API token in Retool Configuration Variables as a secret (Settings → Configuration Variables), not hard-coded in resource settings, to enable rotation without resource reconfiguration
- Leverage Zendesk's search API (/search.json) rather than loading all tickets and filtering client-side — server-side filtering reduces data transfer and respects Zendesk's pagination limits
- Add query caching (30-60 seconds) to read-heavy queries like ticket lists and user lookups to stay within Zendesk's 700 requests/minute rate limit when multiple agents use the dashboard simultaneously
- Use Retool's GUI mode for ticket update queries (PUT requests) rather than building raw JSON bodies in text fields — this reduces the risk of malformed request bodies that silently fail
- Build escalation Workflows in Retool Workflows (not in-app queries) for time-sensitive SLA monitoring — Workflows run on schedules independently of any user session
- When embedding Retool in Zendesk sidebars, pass context via URL parameters rather than storing state in the Retool app itself — this ensures the app always shows fresh data for whichever ticket is currently open
- Implement a Confirm Modal for any destructive operations (ticket deletion, bulk status changes) to prevent accidental modifications in production Zendesk environments
Alternatives
Freshdesk uses a similar REST API pattern with domain-based URLs and API key auth, making it a straightforward alternative for teams who prefer Freshdesk's pricing model or feature set.
Intercom is a better choice if your support team focuses on proactive messaging and conversation management rather than ticket-based queue operations.
Sunshine Conversations extends Zendesk with omnichannel messaging APIs for WhatsApp, SMS, and social — choose this if you need to build messaging workflow panels alongside ticket management.
Frequently asked questions
Does Retool have a native Zendesk connector?
No, Retool does not have a native Zendesk connector. You connect Zendesk via a REST API Resource using Basic Auth with your agent email and API token. The base URL format is https://yoursubdomain.zendesk.com/api/v2/. Despite being a manual setup, this approach gives you full access to every Zendesk API endpoint.
How do I handle Zendesk API pagination in Retool?
Zendesk uses cursor-based pagination in newer API versions and offset-based pagination in v2. The list endpoints return a 'next_page' URL in the response when more results exist. In Retool, add a URL parameter 'page' bound to a Pagination component's current page value, and 'per_page' bound to the page size setting. For search endpoints, use the 'page' and 'per_page' parameters and check the 'count' field in the response to configure the Pagination component's total count.
Can I create Zendesk tickets from Retool?
Yes. Create a query with Method POST, Path /tickets.json, and a JSON body containing the ticket object with required fields: subject, comment.body, and optionally priority, assignee_id, and tags. Use a Retool Form component to collect these fields from your operators. Set the query to run on the Form's submit event handler, then trigger a refresh query on success.
How do I look up requester names instead of just requester_id numbers?
Zendesk ticket responses return requester_id as a numeric ID. To get names, create a secondary query to GET /users/{{ ticketsTable.selectedRow.requester_id }}.json to fetch individual user details, or use the sideload feature by adding ?include=users to your ticket list query. The sideloaded users appear in the response's 'users' array, which you can join to ticket data in a JavaScript transformer.
What is the best way to monitor Zendesk SLA breaches in Retool?
Use Zendesk's search API with a query targeting tickets where the due_at field is in the past: query=type:ticket status:open due<now. Create a Retool Workflow that runs on a schedule (every 15 minutes), fetches these tickets, and sends alerts to Slack or email. In your Retool app, display the same data in a dedicated 'SLA Breached' tab with red status indicators using conditional column formatting in the Table component.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation