Migration · Sep 19, 2026 · 12 min read

Migrating from ManageEngine Service Desk Plus — a field guide

What to bring over, what to leave behind, and how to script the CSV export from SDP into LinaDesk without breaking user history.

Every ITSM migration is a small archaeology project. Ten years of ticket history, three or four generations of custom fields, a half-forgotten SLA rule that only applies during the fiscal year-end freeze — all of it has to survive the move, or the operations team loses institutional memory. This guide is written for the engineer or IT manager who has been handed a ManageEngine Service Desk Plus (SDP) instance and told to move it to LinaDesk before the next renewal cycle.

We assume you have SDP on-premise (Build 14xxx or 15xxx), somewhere between 5,000 and 200,000 historical tickets, an Active Directory-backed user store, and a small handful of email/LDAP integrations. If your SDP is the MSP edition or you are running Enterprise with the CMDB module heavily populated, some of the mapping below will need to be extended — the shape of the work stays the same.

Why organizations migrate off SDP

Before the mechanics, the reasons — because they shape the mapping decisions later. In practice, teams initiating an SDP-to-LinaDesk migration land on one or more of the following:

The reason matters because it dictates what gets carried across. A KVKK-driven migration typically preserves everything, because auditors will ask. A cost-driven migration will happily leave behind features nobody uses.

Phase 1 — Discovery (2 weeks)

The discovery phase exists to prevent the two worst outcomes of an ITSM migration: missing data that turns out to matter and migrated data that turns out to be junk. Two weeks feels long — it is not.

Inventory the SDP instance

Take an honest inventory. From the SDP admin console, capture the following in a shared spreadsheet:

The output is not a document — it is a decision list. Every item is tagged bring, rebuild, or drop. A rule of thumb: if fewer than three tickets in the last twelve months have used a template or custom field, it is a candidate to drop.

Interview the operations team

Discovery is not just an admin-console walk. Sit with three L1 technicians, one L2 lead, and the service desk manager. Ask which reports they open weekly, which macros they use, and which fields they habitually leave blank. The dashboards nobody opens are the fields nobody needs.

Map integration dependencies

SDP is often the hub for adjacent systems: a monitoring tool posts alerts as tickets, an asset-scanner writes CI records, a payroll integration triggers HR onboarding requests. Each of these has to be either re-pointed at LinaDesk's API or paused during cut-over. Miss one and Monday morning brings a stack of orphaned tickets.

Phase 2 — Data mapping

SDP's data model and LinaDesk's are cousins, not twins. The table below is the mapping we use as a starting point; customization always adds rows.

SDP entityLinaDesk entityNotes
RequestersUsers (role: EndUser)Map on UPN, not on internal user_id — see AD section.
TechniciansUsers (role: Technician)Preserve the technician-group membership as LinaDesk Teams.
GroupsTeamsSDP's Support Group ↔ LinaDesk Team is a clean 1:1.
RequestsTicketsPreserve original CreatedAt as CreatedAtUtc (see backdating).
Request notesTicketCommentsPrivate/public flag maps directly.
Request attachmentsAttachmentsBlob storage location changes; URLs in note bodies must be rewritten.
AssetsAssetsSDP's ProductType ↔ LinaDesk AssetCategory.
Asset Additional FieldsCustomFields (scope=Asset)Type mapping: SDP text → LinaDesk string; SDP picklist → LinaDesk enum.
Solutions (KB articles)KnowledgeArticlesApproval status flag preserved.
Categories / Subcategories / ItemsCategory tree (nested)LinaDesk uses a single nested tree; SDP's three-level split is flattened into a path.
SLA PoliciesSlaPoliciesBusiness hours moved to WorkCalendar; see SLA section.
Business RulesAutomationsRewrite required — no direct import.
Change requestsChangesCAB approval chains rebuilt in LinaDesk's ChangeApproval flow.

The rows that require the most engineering time, in our experience, are custom fields, categories, and SLA policies. Everything else is mechanical.

Phase 3 — Export

SDP has three ways to get data out: the built-in scheduled exports, the REST API v3, and direct database access. All three have a place.

The REST API v3 for structured data

The API is the correct source for users, technicians, groups, categories, SLA policies, and any entity you need with its full field set. The endpoints are stable, they respect pagination, and they return JSON that maps cleanly onto our target schema.

A minimal PowerShell script to pull all requests, page by page, into a directory of JSON blobs:

# requires SDP TECHNICIAN_KEY with read access
$sdpUri  = "https://sdp.internal/api/v3/requests"
$authKey = $env:SDP_TECHNICIAN_KEY
$outDir  = "C:\migration\raw\requests"
New-Item -ItemType Directory -Force -Path $outDir | Out-Null

$rowsPerPage = 100
$rowIndex    = 1

do {
  $inputData = @{
    list_info = @{
      row_count   = $rowsPerPage
      start_index = $rowIndex
      get_total_count = $true
      fields_required = @(
        "id","subject","description","status","priority",
        "created_time","resolved_time","closed_time",
        "requester","technician","group","category","subcategory","item",
        "udf_fields")
    }
  } | ConvertTo-Json -Depth 6 -Compress

  $resp = Invoke-RestMethod `
    -Uri "$sdpUri?input_data=$([uri]::EscapeDataString($inputData))" `
    -Headers @{ "authtoken" = $authKey } `
    -Method GET

  $resp.requests | ForEach-Object {
    $_ | ConvertTo-Json -Depth 12 |
      Out-File -Encoding utf8 "$outDir\req_$($_.id).json"
  }

  $total     = $resp.list_info.total_count
  $rowIndex += $rowsPerPage
} while ($rowIndex -le $total)

The equivalent scripts for users, groups, and assets are structural copies. Keep them under version control — you will run them at least three times: once during dry-run, once during rehearsal, once during cut-over.

Direct database read for archived attachments

SDP stores attachments outside the request payload. The API returns metadata but not blobs. For the actual bytes, either use the file-attachment endpoint per record (slow, but respects permissions) or read from SDP's FileAttachment table plus the on-disk Attachments directory. On large instances (100k+ tickets with attachments), the second is the only realistic option — plan an overnight rsync.

Phase 4 — Ticket history preservation

The single most important field in the migration is CreatedAtUtc. If it silently defaults to now, ten years of history compress into a single day and every SLA report becomes meaningless.

LinaDesk supports backdated ticket creation via its bulk-import endpoint. The rule:

Every ticket, comment, status transition, and audit entry carries its original UTC timestamp. Nothing in the import path is allowed to overwrite it.

Concretely: SDP's created_time.value is a Unix millisecond string. Convert to UTC ISO-8601 and pass it as CreatedAtUtc. Do the same for resolved_time, closed_time, and each individual note's created timestamp. If a note has an updated_time that differs from its created_time, preserve both — audit teams occasionally check.

A subtle trap: SDP's timestamps are stored in the account timezone but reported by the API in UTC only if the technician key's user has UTC as its display timezone. Verify this once against three known records before you trust the whole export.

Phase 5 — AD / LDAP re-mapping

Users are almost always the hardest join in the migration. SDP identifies a user internally by its REQUESTERID. Active Directory identifies the same person by their objectGUID. LinaDesk uses ExternalId (which we recommend setting to the AD objectGUID).

The migration cannot rely on either primary key alone. The join we use, in priority order:

  1. UPN (userPrincipalName). This survives AD renames and cross-forest moves. Use as the primary join.
  2. Email address. Falls back if UPN is missing.
  3. sAMAccountName. Last resort, because it is not guaranteed unique across forests.

Any user that fails all three joins goes into a orphans.csv file. In every real migration we have run, this file has between 20 and 400 rows — people who left the company, service accounts that were never linked to AD, and requesters who submitted a single ticket via email in 2018. Decide their fate manually. Do not skip this step: those orphans still own historical tickets and their names must appear correctly in reporting.

Phase 6 — SLA policy remapping

SDP's SLA model is a flat rule engine: match by request criteria, apply response/resolution windows against a business-hour calendar. LinaDesk's model is close but not identical:

The one meaningful gap is around partial pauses. SDP allows SLA to be paused when the ticket is Waiting for Requester. LinaDesk requires the same behavior to be modeled as an explicit PauseOnStatus array in the SLA policy. Do the mapping in the migration script rather than hoping the defaults line up — every SDP instance we have looked at had at least one non-default pause status.

For a longer discussion of the calendar side of SLA design, see the SLA calendar design post — the modeling decisions there apply directly to how you rebuild the calendar in LinaDesk.

Phase 7 — Portal, branding, notification templates

These do not migrate. They rebuild.

SDP's self-service portal is a heavily-templated Zoho-styled shell. LinaDesk's is a modern component-based UI with the same feature surface but a different structure. Copy the visual assets (logo, favicon, brand colors) and the text (welcome message, home-page announcements, category descriptions), and let a designer spend two days rebuilding the portal in LinaDesk's admin UI.

Notification templates are the same story. Extract each email template from SDP as HTML plus a variable list, then rebuild them in LinaDesk's template editor. LinaDesk's variable syntax is {{Ticket.Number}} style; SDP's is $Request.RequestID. Machine-translate the syntax; hand-review the copy.

Phase 8 — The four-week parallel run

Cutting over in a single weekend is a coin flip. Running SDP and LinaDesk in parallel for four weeks is not — it turns a coin flip into an engineering exercise.

Our recommended sequence:

  1. Week -4: LinaDesk deployed. Historical data imported. All L1 technicians have logins and have completed a 90-minute training session. Email routing still points at SDP.
  2. Week -3: Nightly re-import runs against SDP's delta API, keeping LinaDesk within 24 hours of SDP. Technicians are asked to spot-check ten new tickets a day in LinaDesk and file bugs. Portal remains dark.
  3. Week -2: Fifteen percent of inbound email is routed to LinaDesk. Technicians handle both queues. Reports are dual-generated and compared.
  4. Week -1: Fifty percent of inbound routed to LinaDesk. Portal beta open to a small set of pilot requesters. Any P0/P1 discrepancy blocks cut-over.
  5. Cut-over weekend: Final delta re-import. Email routing flipped to 100% LinaDesk. Portal opened to all requesters. SDP set to read-only; kept online for 90 days for audit.

The 90-day read-only period matters. Regulators (and internal audit) occasionally ask questions that require looking at how a ticket looked in the source system on a specific date. Deleting SDP the day after cut-over is a mistake we have seen twice, and both times it ended in an inconvenient legal-hold conversation.

Post-migration validation checklist

Before you sign off:

Common pitfalls

Features that exist in SDP but not in LinaDesk v1

The honest list. LinaDesk v1 does not ship:

If any of these are load-bearing for your operation, resolve it in discovery, not the week before cut-over.

Under-scoping custom-field migration

Every migration we have looked at had at least one custom field that was populated on 60% of historical tickets but on only 3% of the last year's tickets. Someone stopped using it years ago and nobody removed it. Migrate it anyway — orphaned data is still audit-visible data.

Trusting SDP's "date range" export UI

The SDP export UI silently caps rows at 5,000 in some builds and 10,000 in others, and there is no error — just a truncated CSV. Always use the API for anything above a few hundred rows.

Talk to us about your SDP migration

We have run this playbook end-to-end four times in the last eighteen months. If you are planning yours, we will walk you through the discovery template we use.

Contact the LinaDesk team

Related reading