Groove to Pylon Migration: A Technical Guide
Groove to Pylon migration requires a custom API pipeline. No native import exists. This guide covers data mapping, API rate limits, account derivation, and edge cases.
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
Groove to Pylon Migration: A Technical Guide
TL;DR: Groove to Pylon migration requires a custom API-based ETL pipeline — there is no native wizard or one-click import. Groove gives you JSON exports, REST v1, and GraphQL v2 for extraction. Pylon's /import/issues endpoint preserves threaded messages and timestamps for historical data. Pylon's Issues API is rate-limited to 10 requests per minute, making it the primary throughput bottleneck: 600 issues/hour maximum, ~16.7 hours for 10,000 tickets before message and attachment overhead. You must derive Pylon Accounts from Groove customer email domains or Company objects, pre-create Contacts and Tags, and plan for 3–10 business days depending on volume and attachment load.
Migrating from Groove to Pylon means moving from a shared-inbox helpdesk built for email-first support teams to a Slack-first, AI-native B2B platform built around account-centric issue management. The data models are structurally different: Groove is flat (Ticket → Customer → Messages), while Pylon is relational (Account → Contact → Issue → Messages). There is no direct import path between them.
You need a custom ETL pipeline — extract from Groove's export or API, transform to match Pylon's hierarchy, and load via Pylon's REST API. CSV-style approaches lose thread context and attachment links. Middleware tools like Zapier and Make lack the execution time and memory to handle full historical extraction, nested threading, and the relational structure Pylon requires.
For teams evaluating other migration targets from Groove, see our guides on migrating to Zendesk, Gorgias, or Zammad. If you're moving to Pylon from another platform, see Zendesk to Pylon or Freshdesk to Pylon.
Why Teams Move from Groove to Pylon
Groove is a shared inbox and helpdesk that consolidates email, live chat, social messages, and knowledge base content into a single agent workspace. It targets small support teams that need ticketing without enterprise complexity. The core object is the Ticket — an email-centric conversation thread linked to a Customer, with messages, private notes, tags, and assignee tracking.
Pylon is purpose-built for B2B support where conversations happen in shared Slack channels, Microsoft Teams, and Discord. The core object is the Issue — a conversational thread tied to an Account, with messages, internal notes, custom fields, and CRM-synced metadata. The relationship chain is relational: Account → Contact → Issue → Messages.
The typical reasons teams move:
- Channel shift: Groove is email-first; Pylon is Slack/Teams-first. If your customers communicate through shared Slack channels, Groove cannot natively support that workflow.
- B2B account model: Groove ties tickets to individual customers. Pylon groups contacts under Accounts, giving teams company-level visibility into open issues, health scores, and CRM data.
- AI-native capabilities: Pylon ships with AI-generated replies, AI issue QA, and training data management built into the platform. Groove has no equivalent AI layer.
- CRM integration depth: Pylon natively syncs custom fields from Salesforce, HubSpot, and Attio at the Account and Contact level — not just ticket metadata.
Groove vs. Pylon: Data Model Mapping
The fundamental challenge is model translation. Groove's flat structure does not map 1:1 to Pylon's relational hierarchy.
| Groove Object | Pylon Equivalent | Notes |
|---|---|---|
| Ticket | Issue | Core unit. Groove tickets are email conversations; Pylon Issues are multi-channel threads. Use /import/issues for threaded history. |
| Customer | Contact | Groove identifies customers by email. Pylon Contacts belong to Accounts. |
| Company | Account | Groove exposes Company data in GraphQL. Older setups may only have free-text company_name. |
| (no equivalent) | Account | If Groove has no clean Company data, derive Accounts from customer email domains. |
| Agent | User | Map Groove agent emails to Pylon user emails. Pre-create users before loading Issues. |
| Mailbox | Team (partial) | Groove routes tickets to mailboxes. Pylon uses Teams for routing. No direct mapping — manual config required. |
| Folder | View (partial) | Groove folders are saved ticket filters. Pylon Views are filter-based and not importable via API. |
| Tag | Tag | Direct mapping. Create tags in Pylon before loading Issues; reference by slug. |
| Private Note | Internal Note | Groove notes have note: true on messages. Pylon separates internal notes in its message model. |
| Conversation Rating / CSAT | (no equivalent) | Groove CSAT scores and ratings have no corresponding Pylon import field. Store in a custom text field or exclude — see "What You Will Lose." |
| KB Article | KB Article | Separate migration. Groove KB has no bulk export — extract via API or request CSV from Groove support. |
| Custom Fields | Custom Fields | Pylon supports text, number, decimal, boolean, date, datetime, user, url, select, and multiselect. Groove's GraphQL includes ADDRESS, FILE, and MONEY types that need flattening into text, URL, or numeric fields. |
| CC recipients on email threads | Issue participants | Groove captures CC'd addresses per message. Pylon's Issue participant model differs — see the CC handling section below. |
| Conversation State | Issue State | See state mapping below. |
Account derivation is your biggest design decision. Groove may or may not have clean Company data. If it does (via GraphQL's first-class Company objects), map them directly to Pylon Accounts. If your source data relies on free-text company_name fields, you need normalization rules and manual exceptions. For email-only customers, derive Accounts from email domains — but free email providers (gmail.com, yahoo.com, outlook.com) need special handling. Either group them under a catch-all Account or leave those Contacts unaffiliated — Pylon supports both. See the Account Derivation Decision Tree below. (support.usepylon.com)
State Mapping
Groove documents unread, opened, pending, closed, and spam states. Pylon's import supports new, waiting_on_you, waiting_on_customer, on_hold, closed, or a custom status slug. A sensible default mapping:
- Groove
unread/opened→ Pylonnew - Groove
pending→ Pylonwaiting_on_customeroron_hold, depending on your workflow - Groove
closed→ Pylonclosed - Groove
spam→ skip import, or import asclosedwith aspamtag for audit - Groove
snoozed→ Pylonon_hold(note: Groove snooze preserves a wake-up timestamp; Pylon'son_holdstate does not carry a timer — the snooze schedule is lost on import)
This is operational advice, not a vendor-defined default. (groovehq.com)
Extraction: Groove Export and API Options
Groove provides three extraction surfaces. The right choice depends on your volume and requirements.
Groove JSON Export
Groove's admin settings allow Owners and Admins to request a full conversation export in JSON format. The export matches Groove's v1 full conversations format and includes ticket metadata (status, assignee, tags), all messages per conversation, and customer contact information.
Key constraints:
- JSON only — there is no CSV export for conversations
- One export at a time — you cannot queue multiple exports
- Large exports take significant time to generate — Groove's documentation does not publish an exact SLA; allow at least 24 hours for instances over 10,000 tickets and plan accordingly
- Does not include attachments as binary files or KB content
For large Groove instances (10,000+ tickets), use the admin JSON export as your primary extraction source. Then use the API for attachments and knowledge base content that the export doesn't include.
Groove REST API v1 (Deprecated but Functional)
- Base URL:
https://api.groovehq.com/v1 - Auth: Bearer token from account settings
- Key endpoints:
/tickets,/tickets/:number/messages,/customers,/agents,/mailboxes,/folders,/groups,/kb - Pagination: Page-based (
?page=N),per_pagecapped at 50
Groove's REST API v1 is deprecated — Groove states it is "no longer in active development" and recommends the GraphQL API for new integrations. The REST API remains functional and is simpler for one-time extraction scripts. Groove does not always return the full message body in the initial ticket list payload. You must make secondary GET /v1/tickets/{ticket_number}/messages requests to retrieve full threads.
The REST v1 API also does not expose forwarded conversation type (forwarded) as a distinct field — forwarded tickets appear as standard tickets. If your Groove instance uses forwarded conversations heavily, verify field completeness before relying on REST for extraction.
Groove GraphQL API v2 (Recommended)
- Endpoint:
https://api.groovehq.com/v2/graphql - Auth: Bearer API key from
YOUR_SUBDOMAIN.groovehq.com/settings/developer/api - Pagination: Cursor-based
The GraphQL API is the better extraction choice because you can pull a conversation with all its messages, contact info, company data, secondary emails, CC recipients, and tags in a single round trip. It exposes first-class Company and Contact objects useful for building clean Pylon Accounts. (developer.groovehq.com)
Groove notes that its Inbox and Knowledge Base APIs are still being built in GraphQL and recommends REST where needed. A hybrid extractor — GraphQL for conversations and contacts, REST for KB — is often the least painful option.
Groove Rate Limits
Groove's rate limits depend on your plan: 200 calls per minute on Standard, 400 on Plus, and 800 on Pro. You will receive HTTP 429 responses when you exceed them. Build your extraction pipeline with exponential backoff and retry logic on 429s. (groovehq.com)
Do not build the migration off summary fields. Groove's REST summary field is intentionally shortened to ~100 characters. The GraphQL SummaryMessage type is also truncated. For full thread history, use the export JSON or query full conversation data via the API. (help.groovehq.com)
Permissions
Line up permissions early. Groove export requests need an Owner or Admin. GraphQL tokens require admin access. On the Pylon side, only Admin users can create API tokens. This sounds minor until it blocks project kickoff.
Target API: Loading Data into Pylon
Pylon's REST API at api.usepylon.com is your load target. All endpoints require a Bearer token created by an Admin user.
Pylon Rate Limits
Pylon publishes explicit rate limits per endpoint:
| Endpoint | Rate Limit | Notes |
|---|---|---|
POST /issues (Create) |
10 req/min | Primary bottleneck for loading |
POST /issues/{id}/messages |
20 req/min | Message creation |
GET /issues |
10 req/min | Requires time range param, max 30 days per call |
GET /issues/{id}/messages |
20 req/min | Per-issue message retrieval |
GET /contacts, POST /contacts |
60 req/min | Contact operations |
GET /accounts, POST /accounts |
60 req/min | Account operations |
At 10 requests per minute for Issue creation, you can load a maximum of 600 Issues per hour. For a Groove instance with 10,000 tickets, the Issue creation phase alone takes ~16.7 hours — before accounting for message creation, attachment uploads, and retry overhead.
Idempotency and Retry Safety
Pylon's API does not currently document idempotency keys for /import/issues. This means a failed request that partially completed — or a network timeout where the response was lost — can create duplicate Issues on retry. To protect against duplicates:
- Write each Issue's Groove ticket number and Pylon-assigned issue ID to a local state file immediately after a successful response.
- Before submitting any Issue, check the state file for an existing Pylon ID for that Groove ticket number.
- If a duplicate is created accidentally, use
GET /issuesfiltered by yourgroove_ticket_numbercustom field to identify and delete the duplicate before QA.
Building this deduplication layer is not optional for a pipeline that runs 16+ hours — transient failures are guaranteed at that duration.
Pylon Load Order
Pylon Issues reference Accounts and Contacts by ID. You must create parent records first:
- Accounts — Derive from Groove customer email domains or Company data. Create via
POST /accounts. - Contacts — Create via
POST /contactswithaccount_idlinking to the parent Account. - Tags — Create via
POST /tags. Note the slug returned; reference it in Issue payloads. - Custom Fields — Create field definitions via
POST /custom-fieldsbefore loading Issues. - Issues — Create via
/import/issues(historical) orPOST /issues(standard) withcontact_id,account_id, tag slugs, and custom field values. - Messages — If using standard
POST /issues, create messages separately viaPOST /issues/{id}/messages. The/import/issuesendpoint accepts messages inline. - Attachments — Upload via Pylon's attachments API, linked to the correct Issue/Message.
Historical Import with /import/issues
For closed historical tickets, Pylon provides a dedicated /import/issues endpoint that preserves threaded messages, timestamps, and note visibility within a single imported issue. This is the correct path for historical backfill — it accepts issue-level timestamps, tags, attachments, and a messages array with per-message timestamps, privacy flags, and authors.
Pylon does not publish a documented maximum messages-per-payload limit for /import/issues. In practice, very large threads (500+ messages) should be tested in a staging environment before bulk import. Confirm the limit with Pylon support if your Groove instance has long-running ticket threads. (support.usepylon.com)
{
title: "Groove Ticket #1234: Billing API timeout",
account_id: "acc_123",
state: "closed",
created_at: "2024-04-14T09:18:00Z",
updated_at: "2024-04-15T13:54:00Z",
tags: ["billing", "migrated-from-groove"],
custom_fields: {
groove_ticket_number: { value: "1234" }
},
messages: [
{
body_html: "<p>Our billing endpoint is timing out.</p>",
contact_id: "ct_789",
is_private: false,
created_at: "2024-04-14T09:18:00Z"
},
{
body_html: "<p>Checked logs. Reproduced on shard 3.</p>",
user_id: "usr_456",
is_private: true,
created_at: "2024-04-14T09:29:00Z"
},
{
body_html: "<p>Fix is live. Please retry.</p>",
user_id: "usr_456",
is_private: false,
created_at: "2024-04-15T13:54:00Z"
}
]
}Each message requires exactly one of user_id (for agent messages) or contact_id (for customer messages). Build your agent-to-user and customer-to-contact ID maps before running the import. If an agent has left the company and doesn't exist in Pylon, map their messages to a generic system user and prepend their name to the message body (e.g., **[Legacy Agent: Sarah Jenkins]**).
Store the original Groove ticket number in a Pylon custom field (e.g., groove_ticket_number) so you can audit the migration and perform delta syncs. Pylon's documented external_refs examples cover Zendesk and Intercom but not Groove, so a dedicated custom field is the safer pattern.
Imported issues do not trigger AI topic generation. Pylon's /import path does not feed Knowledge Gaps or Feature Requests analysis. If your rollout depends on AI analysis of historical tickets, plan a post-import reprocessing step with Pylon. (support.usepylon.com)
Open vs. Closed Ticket Handling
This distinction matters. Pylon's historical migration path creates static snapshots, not live conversation channels.
For closed tickets, bulk import via /import/issues is the correct approach.
For open email threads, Pylon recommends replying on the existing Groove thread and CCing your Pylon support email address. This creates a new live Pylon ticket that can continue normally — preserving the email thread for the customer. Do not import an open email conversation as a static snapshot; it kills the reply path. (support.usepylon.com)
Handling CC Recipients from Groove Email Threads
Groove captures CC'd email addresses per message. Pylon's Issue participant model works differently: participants are Pylon Contacts or Users, not raw email addresses. When importing CC-heavy Groove threads:
- For each unique CC email found in the thread, look up or create a Pylon Contact.
- Add those contacts as issue participants via Pylon's participant endpoint after issue creation.
- If the CC'd address belongs to a free email domain or is unresolvable, log it in a review queue rather than dropping it silently.
Groove instances that use CC heavily for external stakeholder visibility (e.g., CCing a client's legal team) will need explicit decisions about whether to replicate that pattern in Pylon or restructure it using Account-level contacts.
Attachment Upload to Pylon
Attachments referenced in Groove tickets must be re-hosted in Pylon. The general sequence:
- Download the attachment binary from Groove's CDN using the URL from the export or API response.
- Upload to Pylon using a multipart
POSTto Pylon's attachment endpoint. Pylon returns an attachment ID. - Reference the attachment ID in the message payload when creating the Issue or message.
Pylon's email channel enforces a 10 MB total email size limit and converts oversized attachments into download links automatically. Test with your largest Groove attachments before running the full pipeline to verify behavior on boundary cases. Groove's upload limit is 20 MB per file. Any Groove attachments between 10–20 MB will be handled differently on the Pylon side. (doc.groovehq.com)
Notification Suppression
Pylon notifies users in Slack and via email when issues are updated. The /import/issues endpoint handles historical data without triggering notifications by design. If you use the standard POST /issues endpoint, work with Pylon support to temporarily disable webhooks and notifications during the migration window. Accidentally emailing your entire customer base about four-year-old closed tickets is a bad day.
Account Derivation Decision Tree
This is the most consequential design decision in a Groove-to-Pylon migration. Pylon's account-level views, health scoring, and SLA tracking all depend on Issues being correctly linked to Accounts. Groove may have clean Company data, partial Company data, or none at all.
Does Groove expose first-class Company objects in GraphQL?
├── YES → Map Company directly to Pylon Account (preferred path)
│ └── Does every Customer have a Company linked?
│ ├── YES → Full direct mapping, proceed to Contact creation
│ └── NO → Hybrid: direct map where available, domain-derive the rest
└── NO → Does the Customer record have a `company_name` text field?
├── YES → Normalize company_name strings (trim, dedupe, case-fold)
│ └── Does normalized name have enough signal to trust?
│ ├── YES → Use as Account name
│ └── NO → Fall back to domain derivation
└── NO → Extract email domain
└── Is the domain a free email provider?
├── YES → Leave Contact unaffiliated, OR group under
│ a "Consumer / Unaffiliated" catch-all Account
└── NO → Create Account from domain
Free email domains to filter: gmail.com, yahoo.com, outlook.com, hotmail.com, aol.com, icloud.com, protonmail.com, me.com, icloud.com. Maintain this list as an explicit config file — not hardcoded — so it can be updated without touching pipeline logic.
FREE_DOMAINS = {'gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com',
'aol.com', 'icloud.com', 'protonmail.com', 'me.com'}
def derive_account(customer_email: str) -> str | None:
domain = customer_email.split('@')[1].lower()
if domain in FREE_DOMAINS:
return None # Contact will be unaffiliated
return domainDocument every exception — customers with multiple email addresses spanning different domains, shared domains (e.g., a consultancy's clients all using the same agency domain), and personal domains that look legitimate but represent individuals. These need manual review before import.
Cleaning Up Groove HTML for Pylon
Pylon's import endpoint accepts body_html, but Groove's email HTML is not clean HTML. Email messages contain nested tables, inline CSS, lengthy signatures, and deeply nested blockquote chains from reply history. Pushing this raw into Pylon creates unreadable walls of markup in Pylon's chat-based UI and connected Slack channels.
Specific cleanup rules:
- Strip nested blockquotes: Email replies nest the entire thread history in
<blockquote>tags. Truncate anything below standard reply delimiters (e.g., "On [Date], [Name] wrote:"). Each message already exists as a separate record — the quoted history is duplicated and should be removed. - Remove email signatures: Strip
<div class="signature">blocks and similar patterns. - Clean inline CSS and tables: Remove
styleattributes and convert simple table layouts to plain text where possible. - Handle inline images: Groove stores inline images on its CDN. After you cancel your Groove account, these URLs break. Download all inline images and re-host them before cutover. Replace
<img>tags with references to the new hosted URLs. - Strip forwarded-message headers: Groove's
forwardedconversation type wraps the original email in forwarding headers. Strip these from thebody_htmlbefore import to avoid duplicating metadata already captured in Issue fields.
For the transformation, use an HTML-to-Markdown parser (Turndown for Node.js, html2text for Python) or at minimum strip the HTML down to clean, simple markup before loading.
Step-by-Step Migration Pipeline
Step 1: Audit and Pre-Migration Setup
On the Groove side:
- Export the full JSON dump from admin settings (allow adequate lead time; Groove does not publish an exact SLA for export generation)
- Count total tickets, messages, customers, attachments, and KB articles
- Document all tags, custom fields, mailboxes, and agent assignments
- Identify forwarded conversations and CC-heavy threads — these need special handling
- Identify active integrations (Shopify, Stripe, Slack, HubSpot) — these will not transfer
- Check for CSAT/conversation rating data — decide whether to store in a custom field or exclude
On the Pylon side:
- Create all agent Users and note their IDs
- Build an email-to-userID lookup map
- Create all Tags and note their slugs
- Create Custom Field definitions for any Groove fields you want to preserve (including
groove_ticket_number) - Set up Teams to replace Groove mailbox routing logic
- Configure connected channels (Slack, Teams, email)
- Confirm whether a Pylon staging/sandbox environment is available for dry runs — contact Pylon support to verify availability before building your pipeline against production
Step 2: Build Account Derivation Logic
Follow the decision tree above. Your ETL pipeline needs a function that:
- Checks Groove GraphQL for first-class Company objects per customer
- Falls back to
company_namenormalization if Company objects are absent - Falls back to email domain extraction if no company name exists
- Filters free email domains and routes unaffiliated contacts appropriately
- Writes a local Account map (domain/company → Pylon Account ID) for deduplication across the full customer list
Step 3: Extract and Transform
For each Groove ticket:
- Parse from JSON export (or fetch via API)
- Resolve customer email → Pylon Contact ID (create Contact if not yet created)
- Resolve customer domain/company → Pylon Account ID (create Account if not yet created)
- Map Groove ticket state → Pylon Issue state (including snoozed → on_hold with note that timer is lost)
- Map assignee agent email → Pylon User ID
- Map tags → Pylon tag slugs
- Extract messages in chronological order, preserving the
noteboolean for internal notes - Extract CC recipients per message and resolve to Pylon Contact IDs
- Download attachments from Groove URLs to temporary storage
- Clean HTML message bodies (strip blockquotes, signatures, inline CSS, forwarding headers)
- Write each processed ticket to the local state file before submission
Step 4: Load into Pylon
Follow the load order: Accounts → Contacts → Issues → Messages → Attachments.
Use /import/issues for historical closed tickets. For each issue, construct the payload with the account ID, contact ID, state, tags, custom fields, and the full messages array. After issue creation, add CC-derived contacts as participants.
Respect Pylon's 10 req/min limit on issue creation. At 600 issues per hour, budget your pipeline runtime accordingly. Check the local state file before each submission to avoid duplicates on retry.
Step 5: QA and Validation
After the load completes:
- Compare total Issue count in Pylon vs. ticket count in Groove
- Reconcile counts by state, tag, and date range
- Spot-check 20–50 tickets across different states, agents, and date ranges
- Verify message ordering and note/reply distinction
- Confirm attachment accessibility (especially inline images and any 10–20 MB files)
- Validate custom field values and tag application
- Check that Account and Contact linkages are correct
- Verify CC participants are attached to the correct Issues
- Confirm that CSAT data was stored as intended (custom field or excluded)
Note: GET /issues is rate-limited to 10 req/min and requires start_time / end_time windows no larger than 30 days — structure your validation queries in monthly batches. (docs.usepylon.com)
Step 6: Delta Sync and Cutover
If your team continues using Groove during the migration window:
- Query Groove for tickets created or updated after your initial extraction timestamp
- Load new/updated tickets into Pylon (use the
groove_ticket_numbercustom field for upsert logic; check local state file for existing Pylon IDs before creating) - Move open email threads by replying on the existing conversation and CCing your Pylon support email
- Announce cutover — all agents switch to Pylon
- Disable Groove's incoming email forwarding to prevent split-brain ticket creation
- Set Groove to read-only
Knowledge Base Migration
Groove's knowledge base has no self-serve bulk export feature. Two extraction options: request a KB CSV export through Groove support, or pull articles via the REST v1 /kb endpoint (which supports keyword=*, pagination, state filters, and an unpaginated=true mode capped at 100 results). (help.groovehq.com)
| Groove KB Field | Pylon KB Equivalent |
|---|---|
| Article title | Article title |
| Article body (HTML) | Article body (HTML) |
| Category | Collection |
| Published/Draft status | Published status |
Groove article states include draft, published, wip, and deleted. Do not blindly carry over deleted or half-edited wip content — KB migration is a good cleanup opportunity.
Pylon supports route redirects, so old Groove KB article URLs can redirect to their Pylon equivalents. Set these up before cutover to preserve external links to your documentation.
For small knowledge bases (fewer than 50 articles), manual recreation is often faster than building an automated pipeline. For larger KBs, automate slug capture, collection mapping, publish state, and redirects. (support.usepylon.com)
Edge Cases That Will Break Your Migration
Merged conversations in Groove: Groove allows merging tickets. Merged tickets may contain messages from multiple original customers. Decide which Contact owns the merged Issue in Pylon before import — the pipeline cannot resolve this automatically.
Inline images on Groove's CDN: After canceling your Groove account, all Groove-hosted image URLs break. Download and re-host every inline image before cutover.
Groove's summary field truncation: The REST API summary field is capped at ~100 characters. The GraphQL SummaryMessage is also truncated. Always extract from full conversation data.
Snoozed tickets: Groove's snooze preserves a wake-up timestamp. Pylon's on_hold state does not carry a snooze timer — the scheduled wake-up is lost on import. Import as on_hold and note the original snooze time in a custom field if the timing matters operationally.
Free-domain customers without Accounts: If many of your customers use free email domains, your Pylon instance will have Contacts with no Account parent. This affects Pylon's account-level views, health scoring, and SLA tracking. Plan your strategy using the decision tree before loading.
Forwarded conversations: Groove's forwarded type wraps an original email in forwarding headers. Strip forwarding headers from body_html during the transform step to avoid metadata duplication.
Contacts with multiple companies: If a contact belongs to multiple companies in Groove, decide the primary Pylon Account before import. Do not let the importer guess.
Custom field type mismatches: Pylon does not have direct equivalents for Groove's ADDRESS, FILE, or MONEY custom field types. Flatten these into text, URL, or numeric fields during transform.
Attachment size mismatches: Groove supports up to 20 MB per attachment on upload. Pylon's email channel has a 10 MB total email size limit and converts oversized files into download links. Any Groove attachments between 10–20 MB will behave differently in Pylon — test these explicitly before the full pipeline run.
CC recipients on email threads: Groove captures raw email addresses as CCs. Pylon's participant model requires Contacts, not raw emails. Every CC address needs a Contact record, or you lose the participant data.
CSAT and conversation ratings: Groove captures conversation ratings (positive/negative and optional comments). Pylon has no corresponding import field. If you need this data, store rating and comment in dedicated custom fields (groove_csat_rating, groove_csat_comment) on the Issue.
Very long ticket threads: Pylon does not publish a maximum messages-per-payload for /import/issues. Test threads with 100+ messages in staging before running bulk import.
What You Will Lose
No migration preserves everything. Be explicit with stakeholders about what does not transfer:
- Groove automations and rules — Must be rebuilt as Pylon Triggers and Macros
- Groove reporting history — Pylon generates its own analytics from imported data, but historical trend lines start fresh
- CSAT scores and conversation ratings — No native Pylon import field; must be stored as custom fields or excluded
- Snooze timers — Snoozed tickets import as
on_holdwithout the scheduled wake-up timestamp - Live chat transcripts — Groove live chat sessions may not map cleanly to Pylon's Slack-first model
- Widget configuration — Groove's embedded widget settings do not transfer; configure Pylon's Chat Widget from scratch
- Third-party integrations — Shopify, Stripe, Slack, HubSpot connections must be reconfigured in Pylon
- Folder structure — Groove folders become Pylon Views, which must be manually recreated
- AI topic generation on imported issues — Imported issues do not trigger Knowledge Gaps or Feature Requests analysis
Timeline Estimates
| Groove Instance Size | Estimated Pipeline Runtime | Total Project Duration |
|---|---|---|
| Small (< 1,000 tickets) | 4–8 hours | 2–3 business days |
| Medium (1,000–10,000 tickets) | 1–3 days | 5–7 business days |
| Large (10,000–50,000 tickets) | 3–7 days | 7–10 business days |
| Enterprise (50,000+ tickets) | 7–14 days | 10–15+ business days |
These estimates include audit, pipeline development, runtime, QA, and delta sync. The single biggest variable is attachment volume — a Groove instance with 50,000 tickets and minimal attachments loads faster than one with 5,000 tickets and heavy file attachments. The second biggest variable is Account derivation complexity: instances with clean GraphQL Company data migrate faster than those requiring manual normalization and exception handling.
When to Use a Managed Migration Service
Building a custom ETL pipeline is viable if you have:
- Engineering bandwidth (1–2 developers for 1–2 weeks)
- Familiarity with both Groove's and Pylon's API surfaces
- A testing environment in Pylon for dry runs
- A clear account derivation strategy
- A plan for idempotency and retry safety across a multi-day pipeline run
If you're missing any of these, a managed migration service handles the pipeline, rate limit orchestration, idempotency logic, edge case resolution, and QA.
ClonePartner handles Groove-to-Pylon migrations including account derivation logic, rate limit orchestration across Pylon's 10 req/min ceiling, attachment re-hosting, HTML cleanup, CC participant resolution, and delta sync — typically completing in 3–7 business days with zero downtime.
For more on exporting from Groove, see How to Export Data from Groove: Methods, API Limits & Portability. For Groove migration cost analysis, see Groove Alternatives 2026: Pricing, Migration & Real Costs.
Frequently Asked Questions
- Is there a native migration tool from Groove to Pylon?
- No. There is no native import path, one-click tool, or built-in migration wizard between Groove and Pylon. You need a custom API-based ETL pipeline that extracts from Groove's REST or GraphQL API (or JSON export) and loads into Pylon's REST API.
- How long does a Groove to Pylon migration take?
- Expect 3–10 business days depending on volume. A small instance under 1,000 tickets takes 2–3 days. Larger instances with 10,000+ tickets and heavy attachments take 7–15 days including audit, pipeline development, runtime, QA, and delta sync.
- What is the biggest bottleneck in a Groove to Pylon migration?
- Pylon's Issues API rate limit of 10 requests per minute. This caps Issue creation at ~600 per hour. For instances with thousands of tickets, this single constraint dominates the pipeline runtime.
- Can I import open Groove tickets into Pylon and keep the email thread alive?
- Not through Pylon's historical migration path. Pylon recommends moving active email threads by replying on the existing Groove thread and CCing your Pylon support email, which creates a new live Pylon ticket that can continue normally.
- How do I handle Groove customers without a company in Pylon?
- Pylon organizes Contacts under Accounts. Derive Accounts from customer email domains. For customers on free email providers (gmail.com, yahoo.com), either create a catch-all Account or leave Contacts unaffiliated — Pylon supports both approaches.