Skip to content

Podium to Helpshift Migration: A Technical Guide

Technical guide to migrating from Podium to Helpshift. Covers API-based ETL, data model mapping, Custom Issue Fields, thread splitting, rate limits, and validation.

Rishabh Rishabh · · 26 min read
Podium to Helpshift Migration: A Technical Guide
TALK TO AN ENGINEER

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

Podium to Helpshift Migration: A Technical Guide

Tested against Podium API v4 and Helpshift REST API v1.

Info

TL;DR: Podium → Helpshift Migration

Podium is a messaging, reviews, and payments platform for local businesses. Helpshift is a mobile-first, in-app customer service platform built for apps and games. They share almost no structural overlap. Podium Conversations become Helpshift Issues. Podium Contacts map to Helpshift End User Profiles. Podium Locations map to Helpshift Apps or Tags. Reviews, Payments, and Campaigns have no native Helpshift equivalent — archive or discard them. There is no native migration path. A custom API-based ETL pipeline is the only reliable approach for full-fidelity migration. Budget 80–160 engineer-hours for a mid-size dataset (10K–50K conversations) and expect 2–4 weeks elapsed time.

What Is a Podium to Helpshift Migration?

A Podium to Helpshift migration is the process of extracting contacts, conversations, message history, tags, and metadata from Podium's customer interaction platform and loading them into Helpshift as Issues, End User Profiles, and Custom Issue Fields (CIFs) — while preserving conversation context and contact relationships.

This is a data-model transformation, not a platform swap. Podium is an all-in-one customer interaction platform centered on SMS/text messaging, webchat, Google and Facebook review management, text-based payments, and marketing campaigns for local businesses. Helpshift is a mobile-first customer service platform designed for in-app messaging, AI-driven automation, and issue resolution — primarily used by mobile apps, games, and digital-first companies.

The architectures diverge at the foundation. Podium operates on a location-based, multi-channel messaging model where conversations are tied to physical business locations. A customer texts a business, and that thread can remain open indefinitely. Helpshift operates on an app-based, issue-centric model where support interactions ("Issues") belong to specific applications and move through a defined lifecycle (New → In Progress → Resolved → Rejected). No native "click-to-migrate" tool exists between them.

For related platform migrations, see:

Why Teams Move from Podium to Helpshift

The shift is architectural. Teams migrate for these reasons:

  • Mobile-first support. Podium is designed for local-business SMS and webchat. When the product is a mobile app or game, Helpshift's native in-app SDK is the right foundation. Helpshift provides SDKs for Android, iOS, Unity, React Native, Unreal Engine, Cocos2dx, and Xamarin.
  • In-app messaging over SMS. Podium's messaging is channel-dependent (SMS, email, webchat). Helpshift's messaging is embedded directly inside the app, reducing channel fragmentation and keeping users in-product.
  • AI and bot automation. Helpshift's bot engine supports intent-based automation, FAQ suggestions, and Custom Issue Field-driven routing. Podium's automation is limited to review invites, auto-responders, and marketing campaigns.
  • Issue-based pricing. Helpshift charges per issue created, not per seat or per location. For high-volume support teams with significant bot deflection (>40% deflection rates are common with well-tuned Helpshift bots), this can be substantially cheaper than Podium's per-location pricing.
  • Structured issue management. Helpshift offers Smart Views, SLAs, Automations, Custom Issue Fields, and agent queues. Podium's inbox is conversational but lacks structured ticketing workflows.
  • Scale beyond local business. Podium is optimized for businesses with physical locations (dental offices, auto dealers, retail). Teams building global digital products outgrow Podium's location-centric model and need a platform that scales by app and user volume, not by storefront count.

Core Data Model Differences

These platforms share no common schema. Understanding the structural gap is the first step.

Podium Concept Helpshift Equivalent Notes
Contact End User Profile (via User Hub) Name, email, phone map directly. Attributes → Custom Data or CIF.
Conversation Issue One or more Podium conversations per Helpshift Issue, depending on thread-splitting strategy.
Message Message (within Issue) Direction (inbound/outbound) preserved. Attachments require separate upload.
Location App or Tag One Podium Location can map to one Helpshift App, or use Tags for routing.
Tag Tag Direct mapping. Tags in Helpshift filter Issues into Smart Views.
Attribute (Contact) Custom Issue Field (CIF) or Custom Data Depends on whether data is per-contact or per-issue.
Review ❌ No equivalent Archive externally. Helpshift has no review management.
Payment ❌ No equivalent Archive externally. Helpshift has no payment processing.
Campaign ❌ No equivalent Archive externally. Helpshift has no marketing automation.
Note No native equivalent Serialize into issue messages prefixed with " [Internal Note]" or archive externally.
Webchat Widget Web Chat SDK Requires separate SDK integration — not a data migration item.
Warning

Reviews, Payments, and Campaigns are dead ends. Helpshift has no concept of review management, payment processing, or marketing campaigns. Export these from Podium and archive them in your data warehouse before migration. They cannot be imported into Helpshift.

Migration Approaches

There are four viable paths. Each has different trade-offs around fidelity, effort, and scale.

1. CSV Export + Manual Reconstruction

How it works: Export contacts from Podium via the reporting UI as CSV. Rebuild Helpshift configuration (FAQs, text templates) separately. Accept that historical conversation threading will not be recreated this way. Podium's native contact CSV export includes Name, Phone, Email, Contact Status, Address, Tags, and Date Added. Helpshift's documented CSV imports are for FAQs and text templates, not historical Issue ingestion. (podium.com)

When to use it: Very small datasets (under 1,000 contacts) where conversation history fidelity is not required.

Pros:

  • Lowest technical barrier
  • No OAuth app setup required for the export side

Cons:

  • Podium CSV exports do not include full conversation threading or message bodies
  • Helpshift has no self-service CSV import for Issues — you must use the API or send files to Helpshift support
  • Attachments, message direction, and timestamps are lost or flattened
  • No relationship preservation between contacts and conversations

Scalability: Small datasets only. Breaks down above 1,000 records. Complexity: Low. Risk: False confidence — the CSV looks complete when it is not.

2. API-Based Custom ETL Pipeline

How it works: Build a custom script that extracts data from Podium's REST API v4 (Contacts, Conversations, Messages) and loads it into Helpshift's REST API v1 (Create Issue, Add Message, User Hub Bulk APIs). Store raw extracts in a staging database, transform data to match Helpshift's schema, then load with retry logic and rate limit management.

When to use it: Any migration where conversation history, attachments, and custom fields must be preserved.

Pros:

  • Full control over data transformation logic
  • Preserves message threading, timestamps, attachments, and direction
  • Supports custom field mapping (Podium Attributes → Helpshift CIF)
  • Scriptable, repeatable, testable
  • Supports staged cutover and delta sync

Cons:

  • Requires Podium Developer Account approval (typically 2–5 business days to process)
  • Podium API rate limits vary by endpoint — message-related endpoints are capped at 10 requests/minute, while most read endpoints are limited to 300 requests/minute (docs.podium.com)
  • Helpshift's GET /issues has a pagination ceiling of 50,000 issues per query window (page × page-size ≤ 50,000)
  • Significant engineering effort (80–160 hours for a mid-size dataset)

Scalability: Handles 10K–500K+ records with proper batching and cursor-based pagination. Complexity: High.

Throughput estimates at documented rate limits:

  • Podium contact extraction at 300 req/min with 100 contacts/page: ~50K contacts in ~17 minutes
  • Podium message extraction at 10 req/min: ~600 messages/hour (the bottleneck — a dataset with 100K messages takes ~167 hours of API time without parallelization)
  • Helpshift issue creation (serial, no documented hard limit): plan for ~60–120 issues/minute depending on payload size and Helpshift's throttling response

3. Middleware / iPaaS (Zapier, Make)

How it works: Use Zapier or Make to connect Podium triggers (new message, new contact) to Helpshift actions via custom webhook/API steps. Podium has a Zapier app; Helpshift requires generic HTTP modules. (zapier.com)

When to use it: Ongoing sync of new records after the initial migration. Not suitable for historical data migration.

Pros:

  • No code required for basic setups
  • Good for post-migration live sync of new contacts

Cons:

  • Cannot migrate historical data in bulk
  • No native Helpshift integration on Zapier or Make
  • Rate limits and per-task pricing make bulk operations impractical
  • No attachment handling or conversation threading preservation

Scalability: Individual records only. Not for bulk migration. Complexity: Low for live sync. Useless for historical migration.

4. Managed Migration Service

How it works: Engage a migration service provider who builds and operates the custom ETL pipeline, handles edge cases, runs validation, and manages the cutover.

When to use it: When engineering bandwidth is limited, the dataset is large, or accuracy requirements are non-negotiable.

Pros:

  • No internal engineering time consumed
  • Handles edge cases (duplicates, malformed data, attachment uploads, rate limit management)
  • Includes validation and rollback planning
  • Fastest turnaround

Cons:

  • External cost (typically $5K–$25K+ depending on dataset size and complexity)
  • Requires data access credentials to be shared with the provider
  • Quality varies by vendor — confirm support for Podium conversations, notes, tags, locations, and attachments before signing

Scalability: Any dataset size. Complexity: Low for the customer.

Migration Approach Comparison

Approach Historical Data Conversation Threading Attachments Scale Engineering Effort Main Failure Mode
CSV Export Partial (contacts only) Small Low False sense of completeness
Custom API ETL ✅ Full Any High (80–160 hrs) Poor mapping or retry design
Middleware (Zapier/Make) Individual records Low Timeout and audit gaps
Managed Service ✅ Full Any None (customer) Vendor overpromises

Recommendations by scenario:

  • Small business, < 1K contacts, no history needed: CSV export + manual reconstruction.
  • Mid-size, 1K–50K conversations, history matters: Custom API ETL or managed service.
  • Enterprise, 50K+ conversations, zero-downtime required: Managed migration service.
  • Ongoing sync after migration: Middleware for new records, with API ETL for the initial backfill.

Pre-Migration Planning

Data Audit

Before writing any code, audit what exists in Podium and what needs to move:

  • Contacts: Total count, fields populated (name, phone, email, attributes, tags), percentage with valid email addresses
  • Conversations: Total count, average messages per conversation, date range, percentage with attachments
  • Messages: Total volume, attachment count by MIME type, message types (SMS, email, webchat)
  • Locations: Number of Podium Locations, mapping to Helpshift Apps
  • Reviews: Count and disposition (archive or discard — no Helpshift target)
  • Payments: Count and status (archive — no Helpshift target)
  • Campaigns: Active vs. completed (archive — no Helpshift target)
  • Custom Attributes: List all contact attributes, map to Helpshift CIF types (single-line text, multi-line text, number, date, dropdown, checkbox)
  • Tags: Deduplicate and standardize naming before migration

Define Migration Scope

Not everything should move:

  • Move: Active contacts, conversations from the last 12–24 months, open/unresolved conversations, FAQ content.
  • Archive externally: Reviews, payments, campaigns, conversations older than 24 months.
  • Discard: Test contacts, spam conversations, duplicate records.

Migration Strategy

Strategy Description Best For
Big Bang Migrate everything in a single cutover window Small datasets (< 5K records), weekend migration windows
Phased Migrate by Location or date range in batches Mid-size datasets, multiple business units
Incremental Migrate historical data first, then sync delta before cutover Large datasets, zero-downtime requirements

For most Podium → Helpshift migrations, phased by Location is the safest approach. Each Podium Location maps to a Helpshift App, creating a natural partition boundary.

If you choose incremental, note that Podium webhooks queue events for approximately ten days and time out after five seconds — build your delta collector accordingly. (docs.podium.com)

Timeline Breakdown (Mid-Size Migration, 10K–50K Conversations)

Phase Duration Activities
Week 1 Days 1–5 Data audit, scope definition, Podium Developer Account approval, Helpshift API access request, CIF and App pre-configuration
Week 2 Days 6–10 Build extract scripts, run full extraction, download attachments to S3/GCS, build staging database
Week 3 Days 11–15 Transform layer development, test load of 100–500 records to Helpshift sandbox, agent UAT on test batch, fix mapping issues
Week 4 Days 16–20 Full load, delta sync, record count validation, field-level sampling, cutover, post-migration monitoring

Add 1–2 weeks for datasets exceeding 50K conversations or requiring multi-app routing configuration.

Data Model & Field-Level Mapping

Podium Contact → Helpshift End User Profile

Podium Field Helpshift Field Type Notes
uid identifier String Use as external identifier for deduplication
name name String Direct mapping; trim leading/trailing whitespace
phone phone String Normalize to E.164 format with country code (e.g., +14155551234)
email email String Lowercase, dedupe
createdAt created_at DateTime Preserve original timestamp
tags [] Tags (on Issues) Array Tags are per-Issue in Helpshift, not per-user
attributes{} Custom Data or CIF Key-Value Map each attribute to a CIF type
locations [] App assignment Reference One Location = one App (or use Tags)

Podium Conversation → Helpshift Issue

Podium Field Helpshift Field Type Notes
conversation.uid Custom Issue Field String Store Podium UID in a CIF for cross-reference
conversation.channel.type Custom Issue Field Dropdown Map to "phone", "email", "webchat" — values must be pre-configured in Dashboard
conversation.startedAt created_at DateTime Set via API on creation
conversation.assignedUser assignee_name String Map Podium user → Helpshift agent
Messages Messages within Issue Array Preserve order, direction, timestamps

Podium Message → Helpshift Message

Podium Field Helpshift Field Notes
message.body body Direct mapping. 100,000 character limit in Helpshift.
message.createdAt Timestamp Preserve in message body or metadata. API may not allow timestamp override — prepend to body if needed (e.g., [2023-04-12 14:00 UTC]).
message.sender author Map to "agent" or "user" based on sender type. Note: Podium contact and sender fields on the message object are deprecated — resolve identity from contact and conversation records instead. (docs.podium.com)
Attachments Attachment upload Requires separate API call per attachment. Download during extraction — Podium attachment URLs expire after seven days. (docs.podium.com)

Thread-Splitting Strategy

Podium conversations can run continuously for months or years. A single SMS thread between a customer and a business location may contain interactions about multiple unrelated topics. You have two design choices:

  1. 1:1 mapping: One Podium Conversation = one Helpshift Issue. Simpler, but can result in massive Issues that are hard for agents to navigate.
  2. Time-based chunking: Split a single Podium conversation into multiple Helpshift Issues based on inactivity thresholds (e.g., a 7-day gap creates a new Issue). More complex, but produces cleaner, more actionable Issues in Helpshift.

Choose based on your data. If your average conversation has fewer than 20 messages, 1:1 mapping works. If you have multi-year SMS threads with hundreds of messages, time-based chunking will produce a better agent experience. A common heuristic: if > 25% of conversations exceed 50 messages, implement chunking.

Tip

Custom Issue Field types in Helpshift: Single line text (255 chars max), Multi-line text (100,000 chars max), Number, Date, Dropdown, and Checkbox. Plan your Podium attribute mapping around these six types. If a Podium attribute doesn't fit cleanly, use Multi-line text as a catch-all. Helpshift supports up to 20 global custom user fields and 30 app-level custom user fields. CIF dropdown values must be pre-configured in the Helpshift Dashboard — the API will reject payloads containing undefined dropdown values. (support.helpshift.com)

Migration Architecture

Data Flow: Extract → Transform → Load

Podium API v4                    Transform Layer              Helpshift API v1
─────────────                    ───────────────              ────────────────
GET /contacts        ──►    Clean, deduplicate,      ──►   POST /user-hub/profiles
GET /conversations   ──►    map fields, restructure  ──►   POST /{domain}/issues
GET /messages        ──►    flatten/normalize        ──►   POST /{domain}/issues/{id}/messages
                             attachments              ──►   (multipart upload)
                                    │
                             Staging DB (PostgreSQL/SQLite)
                             S3/GCS for attachments
                             Reconciliation table (Podium UID ↔ Helpshift Issue ID)

Podium API (Source)

  • Base URL: https://api.podium.com/v4/
  • Auth: OAuth 2.0 (requires Developer Account approval via developer.podium.com; typical approval time: 2–5 business days) (docs.podium.com)
  • Key endpoints: GET /contacts, GET /conversations, GET /locations, Webhooks for messages
  • Rate limits: Most read endpoints are limited to 300 requests/minute. Message-related endpoints are capped at 10 requests/minute. Expect HTTP 429 responses on sustained bulk extraction. (docs.podium.com)
  • Pagination: Cursor-based. Contact retrieval uses after parameter. Supports updated_at filter for delta extraction.
  • Gotchas: Podium's contact identifiers are polymorphic — the id parameter can be a conversation UID, email, or phone number depending on context. Standardize on the uid field during extraction. Podium can auto-merge identical contacts, so detect merged identities before loading to avoid duplicate or split identities in Helpshift. (docs.podium.com)
  • Attachments: URLs expire after seven days. Download all attachments during the extract phase. (docs.podium.com)

Helpshift API (Target)

  • Base URL: https://api.helpshift.com/v1/{domain}/
  • Auth: API Key (from Dashboard → Settings → API). Uses HTTP Basic Auth with API key as username and empty password. (postman.com)
  • Key endpoints: POST /issues (Create Issue), POST /issues/{id}/messages (Add Message), User Hub Bulk APIs
  • Rate limits: No hard limit documented on Create Issue API, but Helpshift requires an RPM estimate from your Account Manager. Rate limit settings are managed under Settings > APIs. Plan for throttling on high-volume imports.
  • Pagination (reads): Default 100 issues/page, max 1,000/page. Hard ceiling of 50,000 issues per query window (page × page-size). Use created_since as a time-based cursor to paginate beyond 50K.
  • User Hub Bulk APIs: Limit of 10,000 payloads per request for bulk user profile operations.
  • Bulk Edit: Supports up to 5,000 issue IDs per request for post-load field updates. (postman.com)
  • Archiving: Helpshift automatically archives resolved or rejected issues older than one year. Archived issues are not available through the API or Advanced Search. Do not treat post-go-live API reads as your long-term archive strategy. (support.helpshift.com)
Warning

Helpshift API access is gated. The Integrations feature must be explicitly enabled by Helpshift for your account. Contact your Helpshift Account Manager before starting development. Typical enablement time: 1–3 business days, but can take up to a week during peak periods. This can add days to your timeline — request access in Week 1.

Step-by-Step Migration Process

Step 1: Extract Data from Podium

Pull contacts, conversations, and messages via Podium API v4. Handle cursor-based pagination and rate limits.

import requests
import time
import json
import os
 
PODIUM_BASE = "https://api.podium.com/v4"
HEADERS = {
    "Authorization": "Bearer {access_token}",
    "Content-Type": "application/json"
}
 
def extract_contacts(after_cursor=None):
    """Extract all contacts with cursor-based pagination."""
    params = {"limit": 100}
    if after_cursor:
        params["after"] = after_cursor
    resp = requests.get(f"{PODIUM_BASE}/contacts", headers=HEADERS, params=params)
    if resp.status_code == 429:
        retry_after = int(resp.headers.get("Retry-After", 60))
        time.sleep(retry_after)
        return extract_contacts(after_cursor)
    resp.raise_for_status()
    data = resp.json()
    return data.get("data", []), data.get("metadata", {}).get("cursor", {}).get("after")
 
def extract_all_contacts():
    """Paginate through all contacts."""
    all_contacts = []
    cursor = None
    while True:
        contacts, cursor = extract_contacts(cursor)
        all_contacts.extend(contacts)
        if not cursor or not contacts:
            break
    return all_contacts
 
def download_attachment(url, dest_dir="./attachments"):
    """Download attachment before URL expires (7-day TTL)."""
    os.makedirs(dest_dir, exist_ok=True)
    filename = url.split("/")[-1].split("?")[0]
    filepath = os.path.join(dest_dir, filename)
    resp = requests.get(url, stream=True)
    if resp.status_code == 200:
        with open(filepath, "wb") as f:
            for chunk in resp.iter_content(8192):
                f.write(chunk)
        return filepath
    return None

For each contact, retrieve their conversation history. Download all attachments to secure storage (e.g., AWS S3, GCS) during extraction — Podium's attachment URLs expire after seven days.

Step 2: Transform Data

Clean, deduplicate, and restructure Podium data into Helpshift's schema. If using time-based thread chunking, apply the splitting logic here.

from datetime import datetime, timedelta
import re
 
def normalize_phone_e164(phone, default_country="+1"):
    """Normalize phone number to E.164 format."""
    if not phone:
        return ""
    digits = re.sub(r"[^\d+]", "", phone)
    if not digits.startswith("+"):
        digits = default_country + digits
    return digits
 
def sanitize_text(text):
    """Remove null bytes, invalid UTF-8, and malformed characters."""
    if not text:
        return ""
    # Remove null bytes
    text = text.replace("\x00", "")
    # Encode and decode to strip invalid UTF-8
    text = text.encode("utf-8", errors="ignore").decode("utf-8")
    return text
 
def transform_contact_to_profile(podium_contact):
    """Map Podium Contact to Helpshift User Profile."""
    return {
        "identifier": podium_contact.get("uid"),
        "name": sanitize_text(podium_contact.get("name", "")).strip(),
        "email": (podium_contact.get("email") or "").lower().strip(),
        "custom_data": {
            "podium_uid": podium_contact.get("uid"),
            "phone": normalize_phone_e164(podium_contact.get("phone", "")),
            "source": "podium_migration"
        }
    }
 
def chunk_conversations(messages, max_gap_days=7):
    """Split a long-running conversation into discrete issues by inactivity gap."""
    messages.sort(key=lambda x: x['createdAt'])
    issues = []
    current_issue = []
 
    for i, msg in enumerate(messages):
        if i == 0:
            current_issue.append(msg)
            continue
        prev_time = datetime.fromisoformat(messages[i-1]['createdAt'])
        curr_time = datetime.fromisoformat(msg['createdAt'])
        if (curr_time - prev_time).days > max_gap_days:
            issues.append(current_issue)
            current_issue = [msg]
        else:
            current_issue.append(msg)
 
    if current_issue:
        issues.append(current_issue)
    return issues
 
def transform_conversation_to_issue(conversation, messages, app_id):
    """Map Podium Conversation to Helpshift Issue."""
    first_message = messages[0] if messages else {}
    body = sanitize_text(first_message.get("body", "[No message body]"))
    return {
        "title": f"Migrated: {conversation.get('channel', {}).get('type', 'unknown')} conversation",
        "message-body": body,
        "author": conversation.get("contact", {}).get("email", ""),
        "app-id": app_id,
        "tags": ["podium-migration", conversation.get("channel", {}).get("type", "unknown")],
        "custom_issue_fields": {
            "podium_conversation_uid": {
                "type": "singleline",
                "value": conversation.get("uid", "")
            },
            "original_channel": {
                "type": "dropdown",
                "value": conversation.get("channel", {}).get("type", "sms")
            }
        }
    }

Key transformation rules:

  • Normalize phone numbers to E.164 format (e.g., (415) 555-1234+14155551234)
  • Lowercase all email addresses and trim whitespace
  • Strip null bytes (\x00), malformed emojis, and invalid UTF-8 bytes to prevent Helpshift API 400 errors
  • Resolve Podium's merged contact identities before loading to avoid duplicate users in Helpshift
  • Map Podium Locations to Helpshift Apps or Tags based on your routing strategy
  • Truncate single-line CIF values to 255 characters; use multi-line text for longer values

Step 3: Load into Helpshift

Create user profiles via Bulk API, then create Issues with messages.

HELPSHIFT_DOMAIN = "your-domain"
HELPSHIFT_API_KEY = "your-api-key"
HS_BASE = f"https://api.helpshift.com/v1/{HELPSHIFT_DOMAIN}"
 
def bulk_create_user_profiles(profiles_batch):
    """Bulk import user profiles via User Hub API. Max 10,000 per request."""
    resp = requests.post(
        f"{HS_BASE}/user-hub/bulk/create_core_profiles",
        auth=(HELPSHIFT_API_KEY, ""),
        json={"payloads": profiles_batch}
    )
    return resp.json()
 
def create_issue(issue_payload):
    """Create a single Issue in Helpshift."""
    resp = requests.post(
        f"{HS_BASE}/issues",
        auth=(HELPSHIFT_API_KEY, ""),
        data=issue_payload
    )
    if resp.status_code == 201:
        return resp.json().get("id")
    elif resp.status_code == 400:
        # Common causes: undefined CIF dropdown value, invalid character in body
        log_error("create_issue_400", issue_payload, resp.status_code, resp.text)
        return None
    elif resp.status_code == 429:
        time.sleep(int(resp.headers.get("Retry-After", 30)))
        return create_issue(issue_payload)
    else:
        log_error("create_issue", issue_payload, resp.status_code, resp.text)
        return None
 
def add_message_to_issue(issue_id, message_body, author, attachment_path=None):
    """Add a message (with optional attachment) to an existing Issue."""
    data = {"message-body": sanitize_text(message_body), "author": author}
    files = None
    if attachment_path and os.path.exists(attachment_path):
        files = {"attachment": open(attachment_path, "rb")}
    resp = requests.post(
        f"{HS_BASE}/issues/{issue_id}/messages",
        auth=(HELPSHIFT_API_KEY, ""),
        data=data,
        files=files
    )
    if files:
        files["attachment"].close()
    return resp.status_code == 201
 
def log_error(operation, payload, status_code, response_text):
    """Log failed operations for manual remediation."""
    with open("migration_errors.jsonl", "a") as f:
        f.write(json.dumps({
            "operation": operation,
            "status_code": status_code,
            "response": response_text,
            "payload_id": payload.get("custom_issue_fields", {}).get(
                "podium_conversation_uid", {}).get("value", "unknown"),
            "timestamp": datetime.utcnow().isoformat()
        }) + "\n")

Issues must be created one at a time via the API — there is no bulk Issue import endpoint. After creation, use the bulk edit endpoint (up to 5,000 issue IDs per request) for status, assignee, and tag updates. (postman.com)

Common Helpshift API error responses:

  • 400 Bad Request with "Invalid value for custom issue field" — CIF dropdown value not pre-configured in Dashboard
  • 400 Bad Request with "Invalid character" — null bytes or invalid UTF-8 in message body
  • 401 Unauthorized — API key invalid or Integrations feature not enabled for your account
  • 429 Too Many Requests — rate limit exceeded; check Retry-After header

Step 4: Rebuild Relationships and Enrich

After issues and profiles are created:

  1. Link each Issue to its End User Profile using the author email or identifier.
  2. Apply Tags from Podium conversations to corresponding Helpshift Issues.
  3. Map Podium Location → Helpshift App assignments (if using multi-app setup).
  4. Store the Podium UID ↔ Helpshift Issue ID mapping in a reconciliation table for audit.
  5. Use bulk edit to set assignees, statuses, and operational flags.

Step 5: Run Delta Sync and Validate

Keep Podium live while you ingest deltas from updated_at queries and webhooks, then cut over once record counts, field samples, and agent UAT pass.

Podium webhook payload structure for delta collection:

{
  "event": "message.created",
  "data": {
    "conversationUid": "conv_abc123",
    "message": {
      "uid": "msg_xyz789",
      "body": "Thanks for the update",
      "createdAt": "2024-01-15T09:30:00Z",
      "direction": "inbound"
    }
  },
  "timestamp": "2024-01-15T09:30:01Z"
}

Note: Podium webhooks time out after 5 seconds — your endpoint must acknowledge quickly and process asynchronously. Undelivered events are queued for approximately 10 days. (docs.podium.com)

Edge Cases & Challenges

Duplicate Records

Podium contacts can have duplicate entries across Locations, and Podium can auto-merge identical contacts. Deduplicate by phone number + email before loading into Helpshift. Helpshift's User Hub does not enforce uniqueness — duplicates will be created silently.

Historical Timestamps

Helpshift's Create Issue API sets created_at to the API call timestamp. If the API does not allow overriding created_at on messages, prepend the original timestamp to the message body:

[Original: 2023-04-12 14:00 UTC] Customer: I need help with my order.

Validate the exact write path with Helpshift support before building your loader.

Multi-Location Conversations

A single Podium contact may have conversations across multiple Locations. In Helpshift, each Location maps to an App. Decide whether to consolidate all conversations under one App or preserve the multi-app structure. Consolidation simplifies agent workflows; multi-app preserves organizational boundaries but requires agents to switch between Apps.

Attachment Migration

Podium attachment URLs expire after seven days — download all files during extraction. Helpshift accepts common MIME types (images, PDFs, text files). Upload each attachment via the multipart form endpoint on POST /issues/{id}/messages. There is no bulk attachment import. Unsupported file types should be converted to plain-text links pointing to your secure storage archive (e.g., [Attachment: video.mp4 — https://s3.amazonaws.com/your-bucket/video.mp4]).

Message Ordering

Helpshift Issues display messages chronologically. Load messages in timestamp order. If you create the Issue with the first message body, then append subsequent messages sequentially, threading is preserved.

Podium's Polymorphic Identifiers

Podium's contact retrieval endpoints accept UUIDs, email addresses, or phone numbers as the id parameter. Standardize on the uid field during extraction to avoid 404 errors from ambiguous lookups.

Custom Issue Field Limits

Helpshift enforces strict types for CIFs — single-line text maxes at 255 characters, dropdown values must be pre-defined in the Dashboard before pushing data via the API. The API will reject payloads containing unrecognized CIF keys or undefined dropdown values with a 400 Bad Request. Do not attempt to map every arbitrary Podium tag into a unique CIF — consolidate tags before migration.

API Failures and Retries

Both APIs will return transient errors. Implement exponential backoff with jitter and a maximum of 5 retries. Log every failed request with the full payload for manual remediation.

import time
import random
 
def retry_with_backoff(fn, max_retries=5):
    for attempt in range(max_retries):
        try:
            result = fn()
            if result:
                return result
        except Exception as e:
            base_wait = 2 ** attempt
            jitter = random.uniform(0, base_wait * 0.5)
            wait = base_wait + jitter
            log_error(f"Retry {attempt + 1}/{max_retries}, waiting {wait:.1f}s", str(e))
            time.sleep(wait)
    return None

Searchability After Migration

Helpshift automatically archives resolved or rejected issues older than one year. Archived issues are not available through the API or Advanced Search. If long-term searchability matters, plan for an external archive (data warehouse, Elasticsearch) alongside your Helpshift instance. (support.helpshift.com)

Limitations & Constraints

Constraint Detail
No native migration path There is no Podium-to-Helpshift connector, plugin, or import wizard.
No review management in Helpshift All Podium review data must be archived externally.
No payment processing in Helpshift All Podium payment data must be archived externally.
Helpshift API access is gated Integrations must be enabled by Helpshift. Contact your Account Manager (1–3 business days typical).
50K pagination ceiling Helpshift GET /issues caps at page × page-size ≤ 50,000. Use created_since time-based cursors to work around this.
No bulk Issue import Issues must be created one at a time via the API. No CSV bulk import for Issues.
Attachment re-upload required Attachments must be downloaded from Podium (URLs expire in 7 days) and re-uploaded individually to Helpshift.
Tags are per-Issue, not per-Contact Podium contact-level tags must be migrated as Issue-level tags or Custom Data on the User Profile.
CIF dropdown values must be pre-configured You cannot create dropdown options via the API — set them up in the Dashboard first. API returns 400 for undefined values.
Agent mapping If an agent has left your company, you cannot assign Issues to them without consuming a paid seat. Assign legacy tickets to a generic "Migrated Archive" system user.
CIF quantity limits Helpshift limits the number of Custom Issue Fields you can create. Consolidate tags and attributes before mapping.
1-year auto-archive Helpshift archives resolved/rejected issues after one year. Archived issues are not available through the API or Advanced Search.
10 req/min on Podium messages Message extraction is the primary bottleneck. 100K messages ≈ 167 hours of API time without parallelization.

Validation & Testing

Never execute a full migration without a UAT phase.

Record Count Comparison

Object Podium Count Helpshift Count Match?
Contacts / End User Profiles X X ✅ / ❌
Conversations / Issues X X ✅ / ❌
Messages (total) X X ✅ / ❌
Attachments X X ✅ / ❌

Note: If using thread-chunking, the Helpshift Issue count will exceed the Podium Conversation count. Track the expected expansion ratio (e.g., 10K conversations → 14K issues at 7-day chunking).

Field-Level Validation

Sample 5–10% of migrated records and verify:

  • Contact name, email, phone match source
  • Conversation message count matches
  • Message body content is intact (no truncation, no encoding artifacts)
  • Custom Issue Fields contain the correct mapped values
  • Tags are applied correctly
  • Attachments are accessible and not corrupted

Weight your sample toward long threads (>50 messages) and attachment-heavy conversations — that is where edge cases cluster.

UAT Process

  1. Migrate a test batch (100–500 records) to a Helpshift sandbox or test App.
  2. Have support agents review 20+ conversations for accuracy, covering SMS, email, and webchat channels.
  3. Verify Smart Views, Automations, and routing rules work with migrated data.
  4. Test that CIF dropdown values render correctly in the agent console.
  5. Sign off before running the full migration.

Rollback Planning

Helpshift does not have a "bulk delete" API for Issues. If the migration fails:

  • Tag all migrated Issues with a podium-migration tag for identification.
  • Use the Bulk Edit API to archive or close migrated Issues (up to 5,000 per request).
  • Re-run the migration after fixing the root cause.
  • Maintain the reconciliation table (Podium UID ↔ Helpshift Issue ID) to avoid duplicates on re-run.

For a structured QA approach, see Post-Migration QA Checklist.

Post-Migration Tasks

Rebuild Automations

Podium Automations (review invites, campaigns, auto-responders) do not transfer. Rebuild equivalent workflows in Helpshift using:

  • Automations: Trigger-based rules for issue routing, tagging, and assignment.
  • Smart Views: Filtered queues based on Custom Issue Fields, tags, or issue state.
  • Bots: Configure Helpshift's bot builder for common query deflection.

SDK Integration

Helpshift's value is in-app. Deploy the Helpshift SDK in your mobile app or website:

  • iOS and Android: SDK X (latest generation). Minimum deployment target: iOS 13+, Android API 21+.
  • Web Chat: JavaScript SDK embedded via <script> tag.
  • Game engines: Unity plugin (supports Unity 2018.4+), Unreal Engine plugin, Cocos2dx plugin.
  • Cross-platform: React Native and Xamarin bindings.

Plan 1–2 sprints (2–4 weeks) for SDK integration and testing. This is a development task separate from the data migration.

User Hub Configuration

If you adopted User Hub for identity management, plan a second workstream for live identity and user-field updates. User Hub uses a server-generated JWT model for authentication and requires SDK or API updates for ongoing user profile synchronization — it is not a one-time import. (support.helpshift.com)

Agent Training

Train your team on Helpshift's Agent Console — it operates differently from Podium's location-based inbox. Cover:

  • Smart Views and SLA-driven ticketing queues
  • CIF-based routing and bot handoff workflows
  • Where migrated Podium data lives in Helpshift (document the field mapping for agents)
  • How to identify migrated vs. new Issues (the podium-migration tag)

Monitor for Inconsistencies

Run daily spot checks for the first two weeks post-migration:

  • Are new issues routing correctly?
  • Are migrated conversations accessible and searchable?
  • Are Custom Issue Fields populating as expected?
  • Are resolved migrated issues approaching the 1-year auto-archive window?

Best Practices

  1. Back up everything first. Export all Podium data (contacts, conversations, reviews, payments) to your data warehouse before starting. Treat Podium as read-only during migration.
  2. Pre-configure Helpshift. Create all Custom Issue Fields, dropdown values, Apps, Agent Groups, and Automations in Helpshift before importing data. The API cannot create CIF dropdown options.
  3. Run test migrations. Always migrate a test batch (100–500 records) to a sandbox App first. Validate before scaling.
  4. Use idempotent operations. Store Podium UIDs in a Custom Issue Field on every created Issue. This lets you re-run the migration without creating duplicates — check for existing UIDs before creating.
  5. Run a delta migration. Extract and load historical data up to a specific date. On cutover day, run a delta script that only moves data created after the last extract timestamp. This enables zero-downtime migration.
  6. Validate incrementally. Don't wait until the end to check counts. Validate after each batch of 1,000–5,000 records.
  7. Sanitize data. Strip null bytes, malformed emojis, and invalid UTF-8 bytes during transformation to prevent Helpshift API 400 errors.
  8. Map system IDs. Always store the Podium_Conversation_ID inside a Helpshift CIF. This makes troubleshooting and future audits significantly easier.
  9. Separate archive from live data. Not all historical data needs to be in the agent's primary queue. Use tags or Smart Views to distinguish migrated archive from active issues.
  10. Download attachments immediately. Do not defer attachment downloads. Podium's 7-day URL expiry is the single most common cause of data loss in deferred migration strategies.

When to Use a Managed Migration Service

DIY migration makes sense when you have dedicated engineering bandwidth and a small, clean dataset. It stops making sense when:

  • Dataset exceeds 50K conversations. The pagination and rate-limit management alone consumes weeks of engineering time. At Podium's 10 req/min message rate limit, extracting 500K messages takes ~830 hours of API time.
  • Attachments are critical. Downloading, storing, and re-uploading thousands of files with retry logic is tedious and error-prone.
  • You need zero downtime. Coordinating an incremental migration with a delta sync requires infrastructure your team may not have.
  • Engineering time has a higher-value alternative. Every hour spent on migration scripting is an hour not spent on product.
  • Your Podium tenant has many locations. Multi-location routing and identity resolution adds complexity that scales poorly with DIY scripts.

Two source-specific gotchas make DIY riskier than it looks: Podium can auto-merge identical contacts (creating split identities in the destination), and Podium attachment URLs expire after seven days (breaking any delayed download strategy).

The hidden costs of DIY include: mapping workshops (4–8 hours), retry logic development (8–16 hours), data QA (8–16 hours), agent UAT coordination (4–8 hours), cutover communications, rollback planning, and re-creating routing and automation in Helpshift (8–24 hours).

ClonePartner has completed 1,500+ migrations across help desk platforms, including complex multi-location and multi-app scenarios structurally similar to Podium → Helpshift. We handle the ETL pipeline, edge cases, validation, and cutover — implementing intelligent thread-chunking, managing all API rate limits, and ensuring your agents log into Helpshift with complete, readable customer histories on day one. See how we run migrations.

Sample Data Mapping Reference

Podium Field Helpshift Object Helpshift Field Transform Notes
contact.uid User Profile identifier Preserve as immutable key for deduplication
contact.name User Profile name Trim whitespace, sanitize UTF-8
contact.phone User Profile phone Normalize to E.164 (e.g., +14155551234)
contact.email User Profile email Lowercase, dedupe, trim
conversation.uid Issue (CIF) podium_conversation_uid Store in a single-line CIF (255 char max)
conversation.channel.type Issue (CIF) original_channel Dropdown CIF — pre-configure values: sms, phone, email, webchat
location.name Issue (CIF or Tag) store_location Dropdown CIF or Tag depending on routing needs
message.body Issue Message body Direct mapping; sanitize; 100K char limit
message.createdAt Issue Message created_at Prepend to body if API restricts timestamp override
message.sender Issue Message author Map to Agent ID or Customer ID; use conversation/contact records (deprecated sender field)
tags [].label Issue tags Normalize naming conventions; lowercase, hyphenate
note.body Issue Message or Archive Prefix as " [Internal Note]" or archive externally

Frequently Asked Questions

Can I migrate Podium data to Helpshift using CSV?
Only partially. Podium's native CSV export covers contacts but not full conversation threading or message bodies. Helpshift has no self-service CSV import for Issues — you must use the REST API or send files to Helpshift support. For any migration requiring conversation history, a custom API-based ETL pipeline is required.
What Podium data cannot be migrated to Helpshift?
Reviews, payments, and marketing campaigns have no equivalent in Helpshift. These must be exported from Podium and archived externally (data warehouse, cloud storage) before migration. Helpshift is a support platform, not a reputation or payment management tool.
Does Helpshift have a bulk import API for issues?
No. Helpshift Issues must be created one at a time via the POST /issues API. There is no bulk issue import endpoint. The User Hub Bulk APIs allow importing up to 10,000 user profiles per request, and the Bulk Edit endpoint supports up to 5,000 issue IDs per request for post-load updates.
How long does a Podium to Helpshift migration take?
For a mid-size dataset (10K–50K conversations), expect 2–4 weeks elapsed time and 80–160 engineer-hours for a custom API-based migration. A managed migration service can compress this significantly. Small datasets under 1,000 records can be migrated in under a week.
How should I handle Podium's continuous SMS threads in Helpshift?
You have two options. A 1:1 mapping (one Podium Conversation = one Helpshift Issue) works for short conversations. For multi-year SMS threads with hundreds of messages, use time-based chunking — split conversations into separate Issues based on inactivity thresholds (e.g., a 7-day gap creates a new Issue) to produce cleaner, more actionable tickets.

More from our Blog

Podium to Crisp Migration: A Technical Guide
Migration Guide

Podium to Crisp Migration: A Technical Guide

Technical guide to migrating from Podium to Crisp. Covers API constraints, data mapping, conversation import, field transformations, and edge cases for contacts, messages, and attachments.

Abdul Abdul · · 27 min read
Post-Migration QA: 20 Tests to Run After Your Help Desk Data Migration
Help Desk

Post-Migration QA: 20 Tests to Run After Your Help Desk Data Migration

Ensure your help desk migration is a success with this comprehensive 20-point post-migration QA checklist. This expert guide details the 20 essential tests needed to validate your data integrity, system functionality, user-friendliness, and performance . Learn exactly how to check everything from ticket data, attachments, and knowledge base articles to critical workflows, automations, and integrations before you go live. This process is your final line of defense against lost tickets, broken workflows, and unhappy customers.

Raaj Raaj · · 8 min read