tawk.to to Zendesk Migration: A Technical Guide
A technical guide to migrating from tawk.to to Zendesk — covering data extraction, API constraints, data model mapping, import mechanics, and validation.
Planning a migration?
Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.
Schedule a free call- 1,500+ migrations completed
- Zero downtime guaranteed
- Transparent, fixed pricing
- Project success responsibility
- Post-migration support included
tawk.to to Zendesk Migration: A Technical Guide
Migrating from tawk.to to Zendesk means moving from a free-tier live chat tool into a full-featured, paid ticketing and omnichannel support platform. Similar to a Tidio to Zendesk migration, there is no native migration path — no vendor-built connector, no one-click import, and no shared data format. Every tawk.to-to-Zendesk migration is a custom engineering project that involves extracting data from a platform that wasn't designed for easy bulk export, transforming it to match Zendesk's data model, and importing it through Zendesk's Ticket Import API.
This guide covers the real technical path: structural differences, extraction methods and their limitations, data model mapping, Zendesk import mechanics, edge cases, and validation.
Last verified: July 2025. API behaviors and pricing may change; confirm against current vendor documentation before starting your migration.
Why Teams Move from tawk.to to Zendesk
tawk.to is a free live chat application for monitoring and chatting with website visitors. The free plan includes live chat (widget), email ticketing, a hosted knowledge base, unlimited agents, unlimited chat volume, basic contact management, and access to the reporting dashboard. Paid add-ons cover branding removal, AI Assist, and video/voice support. Its data architecture revolves around Properties (sites), discrete chat sessions, tickets (email-based threads), and contacts (visitors).
Zendesk is a ticketing-first support platform with omnichannel capabilities spanning email, chat, phone, social, and messaging. Current Zendesk plans run $19 (Support Team) to $115 (Suite Professional) per agent per month billed annually, with Enterprise priced via sales quote. Zendesk organizes data around tickets, users (end-users and agents), organizations, groups, and custom fields.
The most common reasons teams migrate:
- Ticketing maturity. tawk.to's ticketing is basic — no SLA tracking, no custom ticket statuses, no multi-level prioritization. Zendesk provides full lifecycle ticket management with SLA policies, custom statuses, and conditional forms.
- Reporting and analytics. tawk.to offers a reporting dashboard but nothing close to Zendesk Explore's custom report builder, cross-channel analytics, or data warehouse export.
- Omnichannel beyond chat. tawk.to is chat-first. Zendesk Suite bundles email, chat, phone, WhatsApp, social messaging, and a help center into a single agent workspace.
- Integrations ecosystem. Zendesk's marketplace has 1,500+ apps. tawk.to integrates with fewer tools, and its REST API is still in private beta.
- Scale and compliance. Larger teams or regulated industries need audit logs, HIPAA eligibility, and role-based access that tawk.to doesn't offer.
tawk.to Data Model vs. Zendesk Data Model
Understanding the structural differences is the foundation of a clean migration.
tawk.to is built around discrete chat sessions and website visitors. Data is organized by Properties (websites). A visitor initiates a chat, an agent responds, and the session ends. If that same visitor returns days later, tawk.to often treats it as a new session unless they're explicitly tracked via an authenticated email.
Zendesk is built around persistent users and tickets. Every interaction must be tied to a specific Requester (an end-user record) and assigned to an Assignee (an agent record). A chat session becomes a single ticket, with individual messages represented as ticket comments.
| tawk.to Concept | Zendesk Equivalent | Notes |
|---|---|---|
| Property | Brand / Subdomain | tawk.to organizes by "Property" (site). Zendesk uses Brands for multi-site setups. |
| Chat (session) | Ticket | tawk.to chats are discrete sessions. Zendesk treats every interaction as a ticket. |
| Ticket | Ticket | tawk.to tickets are email-based threads; maps directly to Zendesk tickets. |
| Contact / Visitor | End-user | tawk.to auto-creates contacts from chats. Zendesk requires users to exist before ticket import. |
| Department | Group | tawk.to departments → Zendesk groups. |
| Agent | Agent (user role) | Agents must be created in Zendesk before importing tickets they're assigned to. |
| Tag | Tag | Direct 1:1 mapping. |
| Knowledge Base article | Help Center article | No native export for tawk.to KB articles; manual or scrape-based extraction. |
| Shortcut (canned response) | Macro | Must be rebuilt manually in Zendesk. No automated migration path. |
| Priority (Low/Medium/High) | Priority (Low/Normal/High/Urgent) | Zendesk adds "Urgent" level. Map tawk.to's three levels to Zendesk's four. |
Field-Level Data Loss Inventory
Not every tawk.to field has a Zendesk equivalent. Before starting your migration, document which fields will be dropped permanently. The table below is the canonical reference:
| tawk.to Field | Zendesk Equivalent | Disposition |
|---|---|---|
| Chat session ID | — | No equivalent. Store in a custom field or tag if traceability is needed. |
| Visitor browser / OS / IP | — | No equivalent. Dropped unless you map to a custom ticket field. |
| Chat rating (thumbs up/down) | Satisfaction rating (CSAT) | Zendesk CSAT is a different mechanism; historical ratings cannot be imported directly. Dropped. |
| Agent response time (per session) | — | No equivalent. Dropped. Zendesk calculates its own metrics post-import and excludes imported tickets. |
| Chat source URL (page where chat started) | Custom field | Maps with transformation — create a URL-type custom field in Zendesk. |
| Visitor geolocation | Custom field | Maps with transformation — requires a custom field. |
| Department (tawk.to) | Group | Maps cleanly. |
| Tag | Tag | Maps cleanly. |
| Shortcut / Canned response | Macro | No import path. Must be rebuilt manually. |
| Property (site) | Brand | Maps cleanly if Brands are configured. |
| Knowledge Base article | Help Center article | Maps with transformation — no export UI; requires API or scraping. |
| Chat transcript text | Ticket comments | Maps cleanly. |
| Ticket subject | Ticket subject | Maps cleanly. |
| Ticket status (Open/Pending/Closed) | Status (Open/Pending/Closed/Solved) | Maps with transformation — tawk.to "Closed" → Zendesk "Solved" or "Closed". |
| Agent email | Agent email | Maps cleanly. |
| Visitor email | End-user email | Maps cleanly when present; anonymous visitors require special handling. |
| Attachment files | Ticket comment uploads | Maps with transformation — requires re-upload via Zendesk Uploads API. |
| Conversation timestamps | Ticket/comment timestamps | Maps cleanly via Ticket Import API. |
tawk.to chats and tickets are separate object types in the Inbox. Decide early whether you're migrating both, or only tickets. Chats without an associated email address cannot create a valid Zendesk end-user, which means the Ticket Import API will reject them unless you handle anonymous visitors explicitly.
Extracting Data from tawk.to
The extraction side is the hardest part of this migration. tawk.to was not built for bulk data portability. Before choosing an extraction method, audit your account: check the total conversation count in your tawk.to dashboard. Accounts under 5,000 conversations can use dashboard exports with manageable manual effort. Accounts above that threshold need scripted extraction via the REST API or a support data dump — the 50-message cap makes dashboard export unworkable at scale.
Method 1: Dashboard Export (Manual)
You can export up to 50 messages at a time from the Inbox. This is the built-in manual export available to admins.
How it works:
- Log in as Admin and navigate to the Inbox for the target Property.
- Select Chats or Tickets in the left menu.
- Use filters (Agent, Status, Tag, Updated date) to narrow your selection.
- Tick the empty checkbox at the top of the list to select all visible chats.
- Click Export, enter a recipient email, and click Send.
- The recipient will receive an email with a link to download a ZIP file containing the chats in JSON format.
For tickets, the process is identical — exports are also delivered as JSON. The download link is valid for 30 days.
For contacts, tawk.to exports separately: you will receive an email with a link to download a .csv with all current contact information for the property.
Limitations of dashboard export:
- 50-message batch cap per export action. For accounts with thousands of chats, this means dozens of manual export cycles.
- Rich text formatting (bold, italics, links) will be stripped in CSV export. JSON export preserves it.
- JSON export includes timestamps, visitor and agent names, message content, and session metadata, but requires custom parsing to reconstruct conversation threads.
- No way to export knowledge base articles via the UI.
tawk.to Chat Export JSON Schema
The dashboard export and REST API return a consistent JSON structure. Here is a representative raw tawk.to chat export payload:
{
"id": "chat_abc123xyz",
"property": "property_789def",
"status": "ended",
"createdAt": "2023-10-14T09:30:00.000Z",
"endedAt": "2023-10-14T09:45:00.000Z",
"department": "Sales",
"tags": ["pricing", "enterprise"],
"rating": "good",
"visitor": {
"id": "visitor_111aaa",
"name": "Jane Smith",
"email": "jane.smith@example.com",
"city": "Austin",
"country": "US",
"browser": "Chrome",
"os": "macOS",
"ip": "198.51.100.0",
"pageUrl": "https://example.com/pricing"
},
"agents": [
{
"id": "agent_222bbb",
"name": "Alex Johnson",
"email": "alex@yourcompany.com"
}
],
"messages": [
{
"id": "msg_001",
"type": "msg",
"sender": {
"type": "visitor",
"id": "visitor_111aaa",
"name": "Jane Smith"
},
"body": "Hi, how much is the enterprise tier?",
"timestamp": "2023-10-14T09:30:00.000Z"
},
{
"id": "msg_002",
"type": "msg",
"sender": {
"type": "agent",
"id": "agent_222bbb",
"name": "Alex Johnson"
},
"body": "Hello! Our enterprise tier starts at $99/mo per seat.",
"timestamp": "2023-10-14T09:32:00.000Z"
},
{
"id": "msg_003",
"type": "file",
"sender": {
"type": "visitor",
"id": "visitor_111aaa",
"name": "Jane Smith"
},
"body": "Can you review this screenshot?",
"file": {
"name": "error_screenshot.png",
"url": "https://cdn.tawk.to/files/error_screenshot.png",
"type": "image/png",
"size": 204800
},
"timestamp": "2023-10-14T09:35:00.000Z"
}
],
"attachments": [
{
"name": "error_screenshot.png",
"url": "https://cdn.tawk.to/files/error_screenshot.png",
"type": "image/png",
"size": 204800
}
]
}Key parsing notes:
messages [].typecan be"msg"(text),"file"(attachment), or system events (e.g.,"info"for agent join/leave). Strip or replace system events — Zendesk rejects empty comment bodies.visitor.emailwill be absent for anonymous visitors. Your script must check for this field's existence before creating the Zendesk end-user.messages [].sender.typedistinguishes visitor messages from agent messages — this determines whether the comment author is the requester or the assignee.- The
ratingfield (e.g.,"good","bad") has no direct Zendesk import equivalent and will be dropped unless you map it to a custom ticket field.
Method 2: REST API (Beta Access Required)
tawk.to has a private beta REST API currently available to partners. To request access: fill out the REST API Access Request Form on the tawk.to developer page. Once approved, you receive a username, password, and a link to the REST API documentation.
The REST API enables programmatic extraction:
- Read full conversation history, manage webhooks, retrieve chat statistics, filter and retrieve lists of tickets, chats, property members, and manage knowledge base articles.
- Base URL:
https://api.tawk.to/v1/ - Authentication: HTTP Basic Auth using the credentials provided upon approval.
- Style: HTTP RPC-style methods.
Approval timeline: tawk.to reviews requests individually. There is no published SLA for approval. Whether you are moving to Zendesk or performing a tawk.to to Freshchat migration, plan for up to several weeks of lead time before building your extraction pipeline around the REST API — and have a dashboard export fallback ready if the timeline slips.
Method 3: Full Data Dump via Support
For high-volume accounts, you can request a complete data export from tawk.to support. This typically arrives as a series of JSON files containing full object relationships — visitors, chats, messages, and properties. This bypasses the 50-message batch cap of the dashboard export but depends on tawk.to's support response time.
If REST API access is delayed and a support data dump isn't forthcoming, your fallback is the 50-at-a-time dashboard export. For large accounts (10,000+ chats), consider scripting a browser automation tool to batch the manual exports — though this is fragile and not officially supported.
Webhooks for Ongoing Data
You can configure webhooks for the following events: Chat starts, Chat ends, New chat transcripts, New ticket is created. Webhooks capture new data after your historical export — they cannot retrieve conversations that occurred before the webhook was configured.
If your endpoint doesn't respond within 30 seconds or returns an error, tawk.to will retry for up to 12 hours.
For a migration, set up a webhook receiver early to capture any conversations that come in between your historical export and your Zendesk go-live.
Preparing Zendesk Before Import
Zendesk operates on strict relational integrity. The Ticket Import API references users, groups, and fields by ID — if they don't exist, the import fails or Zendesk assigns the ticket to the default API user. You must build the scaffolding before importing any tickets. For a broader overview of this sequencing, see our Freshdesk to Zendesk migration checklist.
Set up Zendesk in this order:
-
Agents and Groups. Extract all agent email addresses from your tawk.to export. Use
POST /api/v2/usersto create them withroleset toagent. Map tawk.to departments to Zendesk groups. Agents must be active (not suspended). Capture the returned Zendesk User IDs — you'll need them forauthor_idandassignee_idon imported tickets. -
End-users (Visitors/Contacts). Import your tawk.to contacts as Zendesk end-users before importing tickets. The requester and any comment authors must already exist in Zendesk as active users. The API will reject tickets with suspended or non-existent requesters. The bulk import endpoint (
POST /api/v2/users/create_many) accepts up to 2,000 users per request. Many tawk.to visitors are anonymous — see Handling Edge Cases for strategies. -
Custom fields and ticket forms. If you need custom fields (e.g., tawk.to
pageUrlmapped to a URL field, or chat rating mapped to a dropdown), create them now and note the field IDs — you'll need them in the import payload. -
Brands. If you're mapping multiple tawk.to Properties to separate Zendesk Brands, configure those first.
-
Email channels. Set up support email addresses and verify them before import.
Create a dedicated tag like tawkto_import for all migrated tickets. Zendesk recommends adding a tag to signify these tickets were imported into Zendesk Support and excluding them from any reports that rely on Zendesk-native metrics.
Transforming tawk.to Data for Zendesk Import
Once you've extracted the JSON from tawk.to and scaffolded your Zendesk instance, you need a transformation layer. This is where most of the engineering time goes.
Chat-to-Ticket Conversion Logic
tawk.to chats are real-time conversation sessions with multiple messages. Each imported chat becomes a single Zendesk ticket with multiple comments. Your transformation script must:
- Create one ticket per chat session.
- Map each chat message to a Zendesk comment, preserving the
created_attimestamp. - Set the ticket
requester_idto the Zendesk end-user that corresponds to the tawk.to visitor. - Map agent messages to comments with
public: trueandauthor_idset to the corresponding Zendesk agent. - Map visitor messages to comments with the requester as author.
- Skip or replace messages where
typeis not"msg"or"file"— system event messages (agent joins, agent leaves) produce empty body strings that will cause a 422 error on import.
Ticket-to-Ticket Conversion
tawk.to's email-based tickets map more naturally to Zendesk:
- Subject →
ticket.subject - Message body →
ticket.comment.html_body(orbodyfor plain text) - Priority → Map Low→Low, Medium→Normal, High→High. Zendesk's "Urgent" has no tawk.to equivalent.
- Tags →
ticket.tagsarray - Assigned agent →
ticket.assignee_id(requires the Zendesk agent user ID) - Department →
ticket.group_id - Status → Map Open→Open, Pending→Pending, Closed→Solved (or Closed with
archive_immediately)
Timestamp Handling
You can set the following timestamps on imported tickets: solved_at, updated_at, and created_at. You can also set each comment's created_at timestamp. Timestamps cannot be set before 1970 or in the future.
This is what makes the Ticket Import API essential — it preserves your historical timeline. The standard Tickets API (POST /api/v2/tickets) would stamp everything with the current date, making all historical conversations appear as today's tickets.
Attachment Handling
tawk.to chat exports include attachment URLs pointing to tawk.to's hosted storage. Zendesk will not fetch files from external URLs during import, and tawk.to CDN URLs will eventually break when data is purged or if the URL requires authentication. As we note in our Zoho Desk to Zendesk migration guide, you must fetch and re-host these files before import. Migrate attachments in this sequence:
- Parse attachment metadata: Scan each message object for
type: "file"and extract thefile.urlfield. - Download locally: Have your script download each file to your migration server before tawk.to CDN access expires. Download immediately after export — do not defer this step.
- Upload to Zendesk:
POST /api/v2/uploads?filename={file_name}with the file as binary body. Zendesk returns anupload_token. - Attach to comment: Pass the
upload_tokeninto theuploadsarray of the specific comment in your Ticket Import payload.
{
"author_id": 1234567890,
"value": "Can you review this screenshot?",
"created_at": "2023-10-14T09:35:00Z",
"uploads": ["token_abc123def456"]
}The maximum individual file upload size via the Zendesk Uploads API is 50MB. Files larger than this must be hosted externally and linked in the comment body as plain text URLs.
Importing into Zendesk via the Ticket Import API
Do not use the standard Zendesk Tickets API (POST /api/v2/tickets) for migrations. The standard API:
- Timestamps all tickets with the current date, destroying your historical timeline.
- Triggers all active automations, potentially sending mass emails to customers about years-old conversations.
- Marks all comments as authored by the API administrator, losing original authorship.
Use the Ticket Import API: POST /api/v2/imports/tickets (single ticket) or POST /api/v2/imports/tickets/create_many (batches up to 100 tickets).
Example: Full Transformation
Here is the complete before-and-after transformation for the raw tawk.to export shown earlier:
Input (tawk.to):
{
"id": "chat_abc123xyz",
"createdAt": "2023-10-14T09:30:00.000Z",
"endedAt": "2023-10-14T09:45:00.000Z",
"department": "Sales",
"tags": ["pricing", "enterprise"],
"rating": "good",
"visitor": {
"name": "Jane Smith",
"email": "jane.smith@example.com",
"pageUrl": "https://example.com/pricing"
},
"agents": [{ "email": "alex@yourcompany.com" }],
"messages": [
{
"type": "msg",
"sender": { "type": "visitor" },
"body": "Hi, how much is the enterprise tier?",
"timestamp": "2023-10-14T09:30:00.000Z"
},
{
"type": "msg",
"sender": { "type": "agent" },
"body": "Hello! Our enterprise tier starts at $99/mo per seat.",
"timestamp": "2023-10-14T09:32:00.000Z"
},
{
"type": "file",
"sender": { "type": "visitor" },
"body": "Can you review this screenshot?",
"file": { "name": "error_screenshot.png", "url": "https://cdn.tawk.to/files/error_screenshot.png" },
"timestamp": "2023-10-14T09:35:00.000Z"
}
]
}Output (Zendesk Ticket Import API payload):
{
"ticket": {
"subject": "tawk.to Chat: Pricing Inquiry",
"requester_id": 1234567890,
"assignee_id": 9876543210,
"group_id": 456789123,
"brand_id": 1122334455,
"status": "closed",
"created_at": "2023-10-14T09:30:00Z",
"updated_at": "2023-10-14T09:45:00Z",
"tags": ["tawkto_import", "pricing", "enterprise"],
"custom_fields": [
{ "id": 360001234567, "value": "https://example.com/pricing" }
],
"archive_immediately": true,
"comments": [
{
"author_id": 1234567890,
"html_body": "Hi, how much is the enterprise tier?",
"created_at": "2023-10-14T09:30:00Z",
"public": true
},
{
"author_id": 9876543210,
"html_body": "Hello! Our enterprise tier starts at $99/mo per seat.",
"created_at": "2023-10-14T09:32:00Z",
"public": true
},
{
"author_id": 1234567890,
"html_body": "Can you review this screenshot?",
"created_at": "2023-10-14T09:35:00Z",
"public": true,
"uploads": ["token_abc123def456"]
}
]
}
}Transformation notes:
rating: "good"is dropped (no direct import equivalent).visitor.pageUrlmaps to a custom ticket field (id: 360001234567).- System event messages are excluded entirely.
archive_immediately: trueis set becausestatusis"closed"— this bypasses the normal lifecycle and routes the ticket directly to the archive.- The
tawkto_importtag is added programmatically to every ticket, not sourced from tawk.to.
Key Import API Behaviors
- Trigger bypass: If a ticket with a status other than closed is imported, triggers won't run on the imported ticket. However, if the ticket is updated after import, triggers will resume. This is the most dangerous behavior in the entire migration — a bulk update operation on imported tickets (e.g., a field backfill) can fire mass customer-facing automations.
- No SLA support: Zendesk metrics and SLAs are not supported for imported tickets. Running metrics or SLAs on imported tickets will result in incomplete and inaccurate data.
- Archive immediately: If
archive_immediately: trueis set on a ticket withstatus: "closed", the ticket bypasses the normal ticket lifecycle and is created directly in your ticket archive. - No empty comments: The API returns
HTTP 422 Unprocessable Entityif any comment body is empty or null. Strip system events (agent join/leave, chat timeout messages) and replace with a placeholder like[System event]if you need to preserve the record. - Comment limit per payload: Up to 100 comments per import payload. If a tawk.to chat session exceeds 100 messages, import the first 100 with the initial ticket creation, then use
PUT /api/v2/tickets/{id}to append remaining messages in batches.
Common HTTP Error Responses
| Error | HTTP Status | Cause | Resolution |
|---|---|---|---|
RequesterNotFound |
422 | requester_id does not exist as an active Zendesk user |
Create the end-user before import |
AuthorNotFound |
422 | Comment author_id references non-existent or suspended user |
Create/reactivate the user before import |
| Empty body | 422 | A comment has null or "" body |
Replace with placeholder string |
RecordInvalid |
422 | Malformed timestamp (pre-1970 or future) | Correct timestamp in source data |
| Rate limited | 429 | Exceeded requests-per-minute for your plan | Implement exponential backoff using Retry-After header |
| Payload too large | 413 | Request body exceeds 20MB | Reduce batch size or remove inline base64 images |
Rate Limits and Batching Math
Zendesk API rate limits by plan tier:
- Team: 200 req/min
- Professional: 400 req/min
- Enterprise: 700 req/min
- Enterprise Plus: 2,500 req/min
Using the create_many endpoint at 100 tickets per request on a Professional plan (400 req/min): you can import approximately 40,000 tickets per minute at peak throughput. For 50,000 tickets, that is roughly 2 minutes of pure import time — but account for network latency, attachment upload time, and backoff delays. A realistic estimate for 50,000 text-only tickets with no attachments is 15–30 minutes of active import time. Attachment uploads are serial per file and add significant time: 10,000 attachments averaging 200KB each at 5 seconds per upload adds roughly 14 hours.
Implement exponential backoff with jitter. When you receive a 429, read the Retry-After header value (seconds) and wait that duration before retrying:
import time
import requests
def import_with_backoff(url, headers, payload, max_retries=5):
retries = 0
while retries < max_retries:
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
wait = retry_after + (2 ** retries) # exponential backoff + Retry-After
print(f"Rate limited. Waiting {wait}s (retry {retries + 1}/{max_retries})")
time.sleep(wait)
retries += 1
elif response.status_code in (200, 201):
return response
else:
response.raise_for_status()
raise Exception(f"Max retries exceeded for {url}")Handling Edge Cases
Every tawk.to migration has sharp edges. Here's what to watch for.
Anonymous Visitors (No Email)
tawk.to doesn't require visitors to provide an email address. In practice, anonymous chats represent a significant portion of most tawk.to accounts — any chat initiated without the pre-chat form completed will have no visitor.email field in the export. Your script must check for the existence of visitor.email before attempting end-user creation; attempting to create a Zendesk user with a null email will return a 422.
Your options:
- Placeholder user: Create a single
anonymous@yourdomain.comend-user and assign all unidentified chats to it. Simple but loses visitor-level granularity. - Generated emails: Create synthetic end-users like
visitor-{tawk_visitor_id}@import.yourdomain.com. Preserves 1:1 chat-to-user relationships but clutters your user list. Add a tag or organization to mark them as synthetic. - Skip anonymous chats: If they have no operational value, don't migrate them. This is the cleanest approach for most accounts.
To detect anonymous chats programmatically:
def is_anonymous(chat):
visitor_email = chat.get("visitor", {}).get("email")
return not visitor_email or visitor_email.strip() == ""Multi-Property Accounts
tawk.to lets you run multiple Properties under one account, each with its own chat history and contacts. If you're consolidating into a single Zendesk instance, decide before extraction:
- Do Properties map to Zendesk Brands?
- Do they merge into one Brand with a distinguishing tag (e.g.,
property_site1,property_site2)? - Do contacts across Properties with the same email merge into one Zendesk user? (They should — duplicates will cause import failures if you create the same email twice.)
De-duplicate your end-user list across Properties before creating users in Zendesk. Group by email address and merge visitor records.
Knowledge Base Migration
tawk.to has no KB article export feature in the dashboard UI — this remains an open feature request from the community. Your options:
- Manual copy-paste for small KBs (under 50 articles).
- Web scraping of the public-facing KB pages if they're published.
- REST API — if you have beta access, the API supports listing KB articles and categories programmatically.
Zendesk's Help Center API accepts article creation via POST /api/v2/help_center/sections/{section_id}/articles.json. You'll need to recreate categories as Zendesk sections, re-host any images referenced in article HTML (tawk.to CDN URLs will break), and handle locale mappings if you have multilingual articles.
Canned Responses → Macros
tawk.to "Shortcuts" must be rebuilt as Zendesk macros. There's no dashboard export for shortcuts unless you have REST API access. For small teams this is a 30-minute task. For teams with 100+ shortcuts, use the Zendesk Macros API (POST /api/v2/macros) to bulk-create them from a spreadsheet. Each macro requires at minimum a title and an actions array (e.g., set comment action with the canned text).
Validation and Post-Migration Checks
Never trust a migration until you've validated the output. Run this checklist in a Zendesk Sandbox environment before touching production.
Zendesk Sandbox Validation Workflow
- Enable Sandbox. Zendesk provides a Sandbox environment (available on Suite Growth and above) that mirrors your production configuration. Run your full import pipeline against the Sandbox first.
- Create a Sandbox reset script. Your import will likely fail on the first run. Script the teardown: delete all tickets tagged
tawkto_import, delete synthetic end-users, and reset custom fields before each retry. - Import a representative 1% sample first. Before running 50,000 tickets, run 500. Validate the output thoroughly, fix transformation errors, then run the full import.
- Move to production only after Sandbox passes all checks.
Validation Checklist
- Record counts. Compare the number of chats + tickets in tawk.to against Zendesk tickets tagged
tawkto_import. They must match. If there's a discrepancy, check your import script's error log — 422 rejections are silent unless you capture the response body. - Timestamp integrity. Spot-check 20–30 tickets across different date ranges. Verify
created_atand comment timestamps match the source data. Pay particular attention to timezone handling — tawk.to exports UTC; confirm your transformation script is not applying local timezone offsets. - User linkage. Search for tickets assigned to "(deleted user)" or your default API account. Any such tickets indicate failed
requester_idorassignee_idlookups during import. - Attachment availability. Open 10–15 tickets with known attachments and verify the files download correctly from Zendesk's CDN. Confirm you're not seeing 404 errors on tawk.to CDN URLs.
- Comment ordering. Verify that multi-message chats display comments in chronological order. Zendesk orders comments by
created_at— if any timestamps are identical or inverted, comments will appear out of order. - Tag and field accuracy. Filter by
tawkto_importand confirm the tag imported. Spot-check custom field values (e.g., source URL field) on 10 tickets. - Anonymous visitor handling. Filter by
anonymous@yourdomain.com(or your placeholder) and confirm the count matches your expected anonymous chat volume. - No orphan data. Confirm no tickets landed without a requester, and no end-users were created without associated tickets.
- Error log review. Every 422 error from the import represents a dropped record. Review your error log and determine whether each failure is acceptable (system events, empty messages) or a data loss issue that requires remediation.
If you're running the import against a production Zendesk instance, disable all triggers and automations before importing. Triggers won't run on imported tickets during import, but if any ticket is updated after import — including by a bulk operation during validation — triggers will resume. An accidental update during validation could fire auto-replies to customers referencing years-old conversations.
Cutover Strategy
Because tawk.to lacks a robust historical API, performing a true delta sync — syncing only the conversations that changed between your initial export and go-live — is difficult. The most effective approach is a hard cutover.
- Pre-migration export. Export your historical tawk.to data up to a specific cutoff (e.g., Friday at midnight). Set up your webhook receiver to capture anything new during the transition window.
- Sandbox validation. Run your full import pipeline against Zendesk Sandbox over the weekend. Fix any errors found.
- Production import. Once Sandbox validation passes all checks, run the import against production.
- Widget swap. Replace the tawk.to JavaScript snippet on your website with the Zendesk Web Widget snippet.
- Go-live. On Monday morning, agents log into Zendesk. New chats route through Zendesk Messaging. Historical tawk.to conversations are searchable as closed tickets.
If active chats span the cutover window, agents will need to manually close them in tawk.to and ask the customer to initiate a new conversation via the new widget, or manually recreate the ticket in Zendesk.
For strategies on running parallel systems during a migration, see our guide on zero-downtime help desk data migration.
Migration Timeline and Effort
Realistic timeframes based on account size:
| Account Size | Chat + Ticket Volume | Estimated Effort | Primary Bottleneck |
|---|---|---|---|
| Small | Under 5,000 | 2–4 days | Dashboard export manual batching |
| Medium | 5,000–50,000 | 1–2 weeks | Scripted extraction, transformation logic |
| Large | 50,000+ | 2–4 weeks | REST API access approval, attachment re-hosting |
The biggest variable is extraction. If you get tawk.to REST API access quickly, the export side is straightforward. If you're stuck with dashboard exports, add 50–100% to your timeline for manual batch work. Attachment handling is the second-biggest variable: accounts with high attachment volume should allocate a dedicated download step immediately after export, before CDN URLs expire.
When to Proceed Yourself vs. Bring in Help
Proceed with an in-house migration if:
- Your volume is under 5,000 conversations.
- You don't need to preserve attachments.
- You have engineering capacity to write and test custom transformation scripts.
- You're comfortable navigating tawk.to's gated API approval process.
Bring in specialized help when:
- You have tens of thousands of chats and tickets across multiple Properties.
- You need zero-downtime migration with a parallel-run period.
- Attachment URLs are time-limited and must be captured in a tight window.
- You've been waiting for tawk.to REST API access and need an alternative extraction strategy.
- Your Zendesk instance has complex custom fields, multiple Brands, or strict SLA requirements that demand precise data mapping.
- You cannot afford data loss from 422 rejections going undetected.
At ClonePartner, we handle extraction, transformation, and import end-to-end — including edge cases like anonymous visitor handling and attachment re-hosting.
Frequently Asked Questions
- Can I migrate tawk.to chat history to Zendesk automatically?
- No. There is no native connector or one-click tool. You must export tawk.to chats as JSON (manually or via the gated REST API), write a transformation script to map the data to Zendesk's ticket format, and import via the Zendesk Ticket Import API.
- How do I export all my data from tawk.to?
- Chat and ticket exports are done from the tawk.to Inbox dashboard as JSON files, 50 messages at a time per batch. Contacts export as CSV. For bulk programmatic export, you can request access to tawk.to's private beta REST API, though approval timelines vary. You can also request a full data dump from tawk.to support for high-volume accounts.
- Why should I use the Ticket Import API instead of the standard Zendesk Tickets API?
- The standard Tickets API overwrites historical timestamps with the current date, triggers all active automations (potentially sending mass emails to customers), and marks all comments as authored by the API administrator. The Ticket Import API preserves created_at timestamps, bypasses triggers, and lets you set author_id per comment.
- What happens to tawk.to chats from anonymous visitors without email?
- Zendesk requires every ticket to have a valid requester. For anonymous tawk.to visitors, you can create a placeholder end-user, generate synthetic email addresses per visitor ID, or skip anonymous chats entirely if they have no operational value.
- How long does a tawk.to to Zendesk migration take?
- Small accounts (under 5,000 conversations) can finish in 2–4 days with manual export. Medium accounts (5,000–50,000) typically take 1–2 weeks with scripted extraction. Large accounts (50,000+) may require 2–4 weeks due to tawk.to's export limitations and attachment handling.


