greytHR to Keka Migration: The Complete Technical Guide
A technical guide to migrating from greytHR to Keka — covering greytHR API extraction, statutory data mapping, Keka load sequence, and payroll validation.
Planning a migration?
Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.
Schedule a free call- 1,500+ migrations completed
- Zero downtime guaranteed
- Transparent, fixed pricing
- Project success responsibility
- Post-migration support included
greytHR to Keka Migration: The Complete Technical Guide
TL;DR — greytHR to Keka Migration
Moving from greytHR to Keka requires translating a compliance-first, flexible payroll architecture into Keka's strict Pay Group and Salary Structure hierarchy. You cannot export from one and import to the other without transformation. Extraction from greytHR requires combining the REST API (v2), the Query Builder, and UI report exports — no single method gives you everything. A successful cutover demands precise mapping of Indian statutory components (PF, ESI, PT), exact YTD payroll figures for accurate TDS calculation, and a strict load sequence (Org → Pay Groups → Employees → Salary → Leave → YTD). Expect to rely on Keka's Excel bulk import templates for the initial load, reserving the API for documents and ongoing integrations.
Disclosure: This guide is published by ClonePartner, an engineer-led data migration service. Technical claims are based on field experience with mid-market Indian payroll migrations, greytHR API v2 documentation, and Keka API v1 documentation.
Migrating between two India-focused HRIS platforms that both handle payroll, leave, attendance, and employee lifecycle sounds straightforward. It is not. greytHR is a compliance-first payroll engine with deep statutory automation covering Indian labour acts. Keka is a broader HR platform with a built-in ATS, performance management (OKRs, 360-degree feedback), and Professional Services Automation (PSA) — but enforces a stricter structural hierarchy for its payroll engine.
If you attempt a direct field-to-field mapping without understanding how Keka calculates Tax Deducted at Source (TDS) based on historical Year-to-Date (YTD) data, your first payroll run will fail. Employees will see incorrect tax deductions, statutory filings will mismatch, and your finance team will face a reconciliation crisis.
This guide covers extraction from greytHR via API and UI exports, field-level mapping to Keka's data model, API constraints on both sides, the load sequence that avoids referential integrity failures, a worked YTD TDS example, salary structure consolidation decision rules, and the cutover and rollback process needed for zero-downtime payroll operations.
For a broader migration framework, see The Ultimate HRIS Data Migration Checklist. If your migration involves sensitive payroll or compensation data, review How to Safely Migrate Sensitive Employee & Payroll Data.
Why Teams Move from greytHR to Keka
The most common trigger is outgrowing greytHR's core HR feature set. greytHR excels at Indian statutory payroll compliance — PF, ESI, TDS, professional tax, Form 16 generation — but teams expanding beyond pure payroll hit walls:
- No built-in ATS. greytHR's recruitment capabilities are limited. Keka ships a full applicant tracking system (Keka Hire) with career pages, job board posting, and candidate pipelines.
- Basic performance management. Keka supports OKRs, 360-degree feedback, 9-box grids, and goal cascading. greytHR treats performance as a secondary module.
- Project and timesheet tracking. Keka includes PSA with timesheets and project-level cost tracking. greytHR does not.
- Broader API surface. Keka's REST API covers more HR entities and has a documented developer portal with a sandbox environment, making integrations easier to build.
The reverse consideration: greytHR has deeper statutory compliance automation and lower entry pricing, including a freemium tier for up to 25 employees. If compliance automation is the primary concern and the team doesn't need ATS or performance management, greytHR may still be the better fit.
A note on ATS data: If your organization was using greytHR's limited recruitment module, that candidate pipeline data has no import path into Keka Hire. Export candidate records as CSV from greytHR's recruitment module before cutover and manually reconstruct active pipelines in Keka Hire. Closed positions can be archived as documents.
How to Extract Data from greytHR
greytHR data extraction requires combining three methods: the REST API (v2), the Query Builder, and UI-based report exports. No single path gives you everything.
greytHR API v2
The greytHR REST API uses a base URL of https://api.greythr.com and requires two headers on every request: an ACCESS-TOKEN (bearer-style) and an x-greythr-domain header identifying your company instance. Authentication uses OAuth 2.0 client credentials flow.
Key endpoints for extraction:
| Entity | Endpoint | Notes |
|---|---|---|
| All employees | GET /employee/v2/employees?page={page}&size={size} |
Paginated, returns in content array |
| Employee profile | GET /employee/v2/employees/profile |
Name, photo, basic info |
| Personal details | GET /employee/v2/employees/personal |
Address, emergency contacts |
| Work details | GET /employee/v2/employees/work |
Department, designation, manager |
| PF & ESI details | GET /employee/v2/employees/pf |
Statutory identifiers |
| Separation details | GET /employee/v2/employees/separation |
Exit dates, reasons |
| Leave balances | GET /leave/v2/employee/years/{Year}/balance |
Per-year snapshot |
| Leave transactions | GET /leave/v2/employee/transactions?start={date}&end={date} |
Date-range required |
| Attendance muster | GET /attendance/v2/employee/muster |
Daily attendance records |
| Salary statement | GET /payroll/v2/employees/salary/statement/{yyyy-mm-01} |
Month-wise payroll |
| Salary repository | GET /payroll/v2/salary/repository |
Salary component definitions |
| Employee documents | GET /employee/v2/emp-docs/{employeeId}/{categoryId} |
Per-employee, per-category |
greytHR does not publish fixed rate limits. The official documentation does not specify an explicit requests-per-minute cap. In migrations of 500–2,000 employees, we have observed consistent 429 (Too Many Requests) errors above approximately 40 requests per minute. Sustained throughput of 30 requests per minute is stable across extended extraction runs. Implement exponential backoff starting at 2 seconds, doubling on each retry up to a 60-second ceiling. The default pagination size is 25 records per page — plan your extraction loops accordingly.
What the API Cannot Extract
Several greytHR data categories have no API coverage or require workarounds:
- Org configuration (leave policies, shift rules, approval workflows) — not exposed via API
- Documents — requires per-employee, per-category API calls; no bulk download endpoint
- Custom fields — coverage varies; some custom data may only be accessible via UI exports
- Historical payroll runs — salary statements can be pulled month by month, but reconstructing full payroll history requires iterating across every pay period
- Form 16 / tax computation details — available as a download endpoint but returns binary (PDF), not structured data
UI-Based Extraction: Reports Gallery and Query Builder
For data the API doesn't cover, greytHR's admin portal offers two key reporting tools:
Reports Gallery contains pre-built reports downloadable as PDF, XLS, or DOC. Categories include payroll registers, statutory reports (PF/ESI returns), attendance summaries, and employee directories.
Query Builder (Reports > Query Builder) is the most flexible UI extraction path. It lets administrators construct SQL-like queries through a UI, selecting output fields from available categories, applying filters, and exporting to Excel. To build a complete migration payload, generate distinct extracts for:
- Employee Master Data: Core demographics, joining dates, confirmation dates, contact details.
- Statutory Details: UAN (Universal Account Number), PF Account Number, PAN (Permanent Account Number), Aadhar, ESI (Employee State Insurance) numbers.
- Bank Details: Account numbers, IFSC codes, bank names.
- Salary Structures: Current effective-dated breakdown of CTC (Cost to Company), Basic, HRA (House Rent Allowance), Special Allowances, and custom components.
- Leave Balances: Current accrued balances for Privilege Leave (PL), Sick Leave (SL), and Casual Leave (CL).
greytHR also offers an Analytics Hub (Employee > Main > Analytics Hub) that allows pivot tables, custom templates, and Excel exports of employee data with grouping and filtering.
Extracting YTD Payroll Data
If you are migrating mid-financial year (e.g., October), Keka needs to know exactly how much salary was paid and how much tax was deducted from April to September. Without this, Keka will calculate TDS for the rest of the year incorrectly.
Extract the YTD Payroll Register from greytHR — either via the salary statement API endpoint (iterating month by month) or from the Reports Gallery. This data must include month-by-month breakdowns of all earnings, deductions, and tax exemptions claimed by the employee.
For historical payslips and Form 16s, greytHR allows bulk downloads via the UI in zip format. These are PDF binaries — not structured data. You will need to map these files back to employee IDs using the file naming conventions (which typically include the greytHR employee ID) before uploading them to Keka.
greytHR to Keka: Data Model Differences
The core structural difference: greytHR organizes employees around statutory compliance categories (PF establishment, ESI branch, professional tax slab), while Keka organizes employees around business structure entities (legal entity, business unit, department, location, pay group). Fields that are implicit or flat in greytHR become required lookup references in Keka.
Field Mapping Reference
| greytHR Field/Concept | Keka Equivalent | Migration Notes |
|---|---|---|
| Employee Number | Employee Number | Direct map; ensure uniqueness across entities |
| Department | Department | Must pre-exist in Keka before employee import |
| Designation | Job Title | Terminology differs; may need value mapping |
| Location | Location | Must be created under correct Legal Entity in Keka |
| Reporting Manager | Reporting Manager | Mapped by employee number; manager must be imported first |
| PF Establishment | Pay Group + statutory config | Keka ties PF/ESI to pay groups, not standalone entities |
| ESI Branch | Pay Group + statutory config | Same as above |
| Leave Policy | Leave Policy (under Leave Plan) | Must be recreated in Keka; no direct import path |
| Shift Assignment | Shift Timing | Configured in Keka's Attendance module separately |
| Salary Components | Salary Structure (CTC Template) | Keka uses CTC-based salary structures; component mapping is manual |
| Employee Documents | Employee Documents | Keka supports folder-based batch upload |
Pay Groups and Salary Structures: How They Relate
In Keka, Pay Group and Salary Structure are distinct but dependent entities. A Pay Group defines the payroll cycle, statutory settings (whether PF/ESI applies), and which Salary Structures are valid within it. A Salary Structure (also called a CTC Template) defines the mathematical rules for splitting CTC into components — percentages, fixed amounts, or formula-based calculations. An employee belongs to one Pay Group and is assigned one Salary Structure within that group.
In greytHR, you might have individual employees with highly customized salary components added ad-hoc. In Keka, you must define standardized Salary Structures at the organizational level, and individual employees are assigned to a structure with their CTC amount. Keka then auto-calculates component breakdowns based on the template rules.
Example: An employee earning ₹12,00,000 CTC annually assigned to a Keka CTC template configured as Basic = 40%, HRA = 20%, Special Allowance = 25%, LTA = 10%, Medical = 5% would have components calculated as:
| Component | Percentage | Annual | Monthly |
|---|---|---|---|
| Basic | 40% | ₹4,80,000 | ₹40,000 |
| HRA | 20% | ₹2,40,000 | ₹20,000 |
| Special Allowance | 25% | ₹3,00,000 | ₹25,000 |
| LTA | 10% | ₹1,20,000 | ₹10,000 |
| Medical | 5% | ₹60,000 | ₹5,000 |
| Total CTC | 100% | ₹12,00,000 | ₹1,00,000 |
If the same employee in greytHR had a manually assigned Medical Allowance of ₹7,500/month (not 5% of CTC), you cannot simply import that value — you must either adjust the Keka template percentage to reflect the actual amount at that CTC level, or override the component value per employee (Keka allows per-employee overrides within a structure). Document every such override during transformation.
Salary Structure Consolidation Decision Framework
greytHR's per-employee component flexibility means you may encounter dozens of salary variations in your extract. Before building Keka structures, apply this decision framework:
Step 1: Cluster employees by component pattern. Group employees whose salary breakdown follows the same percentage or fixed-amount rules. Two employees with Basic=40%, HRA=20%, SA=25%, LTA=10%, Medical=5% belong to the same cluster regardless of their CTC amount.
Step 2: Apply the threshold rule.
- Fewer than 5 employees share a component or component variant → Map to a generic "Special Allowance" component within the closest matching structure. Do not create a dedicated structure for edge cases.
- 5 or more employees share a distinct component pattern → Create a named Salary Structure in Keka for that pattern (e.g., "Metro - Standard Tier 1", "Non-Metro - Field Staff").
- A single employee has a unique custom component not present anywhere else → Use Keka's per-employee component override. Document it for HR review.
Step 3: Validate metro/non-metro split. HRA tax exemption (Section 10(13A)) differs between metro cities (50% of Basic exempt) and non-metro (40% of Basic exempt). Create separate Salary Structures for metro and non-metro locations if HRA percentages differ, even if all other components are identical.
Step 4: Confirm PT state mapping. Professional Tax slabs are state-specific. An employee in Maharashtra has a different PT structure than one in Karnataka. Salary Structures linked to locations in different PT states must be separated or have PT configured at the Pay Group level with location-based overrides.
Section 80C/80D Investment Declaration Handling
greytHR stores employee investment declarations (Section 80C — PPF, ELSS, LIC premium; Section 80D — health insurance premium; HRA claims; home loan interest) as structured records tied to the employee's tax computation for the financial year.
Keka accepts these declarations through its Tax Declaration module (accessible to employees via self-service, or importable by payroll admin). The import path for declarations is:
- Export tax declaration data from greytHR (Reports > Payroll > Investment Declaration Report) as Excel.
- Map each declaration type to Keka's taxonomy — greytHR's category names may differ from Keka's (e.g., greytHR "LIC Premium" maps to Keka "Life Insurance Premium" under 80C).
- Import via Payroll > Payroll Admin > Tax Declarations using Keka's declaration import template, specifying employee number, declaration category, declared amount, and proof status (submitted/not submitted).
If declarations were stored as PDFs in greytHR: You cannot import the dollar amounts from PDFs without manual extraction or OCR. For a mid-year migration, prioritize importing declarations for employees whose year-to-date TDS is most sensitive to declaration amounts — typically employees in the ₹10–20 lakh annual CTC range where 80C declarations have the largest marginal TDS impact.
Critical: If employee declarations are not imported before the first Keka payroll run, Keka will compute TDS without any 80C/80D relief. For an employee declaring ₹1,50,000 under 80C in the 30% tax slab, this creates a TDS overcollection of ₹46,800 for the year. Employees in higher tax brackets notice this immediately. Load declarations before unlocking payroll.
Statutory Identifier Validation
Indian payroll requires strict validation of statutory identifiers. Keka will reject imports if formats are invalid:
- PAN: Exactly 10 alphanumeric characters (e.g., ABCDE1234F)
- Aadhar: Exactly 12 digits
- UAN: Exactly 12 digits
- IFSC: Exactly 11 characters
Cleanse this data in your transformation layer. greytHR sometimes allows dummy data (like "NOT APPLICABLE") in older records. Keka's import validators will flag these, causing the entire row to fail.
What You Cannot Migrate Directly
- Processed payroll history. Keka generates payslips from its own payroll engine. You cannot import greytHR's historical payslips as processed payroll. Store historical payslips as documents in Keka's document management system.
- Leave transaction history. You can set opening leave balances in Keka, but individual leave transaction records (approvals, cancellations) from greytHR do not have an import path.
- Statutory filing history. PF ECR files, ESI returns, and Form 16 data generated in greytHR belong to greytHR's compliance engine. Export PDFs for reference but they cannot be imported into Keka's compliance module.
- Approval workflow configuration. Workflows must be rebuilt manually in Keka.
What Is the Correct Load Sequence for Keka?
Keka enforces strict referential integrity. You cannot load an employee if their department does not exist. You cannot assign a salary if the Pay Group does not exist. For bulk migrations, Keka's Excel import templates are more efficient than the REST API for initial data loading.
Keka accepts data through two primary channels: Excel-based bulk import (via Global Settings > Data Import) and the REST API (OAuth 2.0, 50 requests/minute, default page size 100, maximum page size 200). Execute your load in this sequence:
- Organizational Infrastructure: Legal Entities, Business Units, Departments, Designations, and Locations. These are configured manually in Keka's admin settings — there is no bulk import for org structure. For multi-entity organizations, each Legal Entity requires its own statutory configuration (separate PF establishment codes, separate ESI branch codes, separate professional tax registrations). Employees belonging to different legal entities cannot share a Pay Group.
- Leave & Attendance Policies: Define the rules before assigning them to users.
- Pay Groups & Salary Structures: Configure the statutory rules, CTC templates, and component math. Get this right the first time — pay group reassignment after employee creation erases all payroll data for that employee.
- Employee Master: Load core demographic and job data using Keka's bulk import (Global Settings > Data Import > Employee category). Download the Excel template, which includes fields for legal entity, business unit, department, location, reporting manager, and shift timing.
- Employee Personal & Bank Details: Addresses, emergency contacts, bank account numbers, IFSC codes — each has its own import template.
- Statutory Details: PF numbers, UAN, ESI numbers — imported via payroll operations import (Payroll > Payroll Admin > Operations).
- Salary Assignment: Assign employees to their respective Pay Groups and Salary Structures, specifying the effective date.
- Tax Declarations: Import Section 80C/80D/HRA declarations before running payroll. See above section.
- Leave Balances: Import active leave balances as of the cutover date.
- YTD Payroll Data: Load previous months' earnings and tax deductions.
- Documents: Bulk upload via Employee Documents section using folder-based batch uploads.
Pay group reassignment destroys payroll data. When you reassign a pay group for an employee in Keka, all payroll data for that employee is lost — salary structures, PF/ESI establishment IDs, everything. Get pay group assignments right on the first import. If you discover an error post-import, you will need to re-enter salary data and statutory details manually.
The Effective Date Trap. When importing Salary Assignments and YTD data, effective dates are critical. If you are cutting over on October 1st, the salary assignment must be effective October 1st. The YTD data must cover April 1st to September 30th. Overlapping dates will cause Keka's payroll engine to double-count earnings or throw validation errors.
Using Keka's Excel Import
For organizations under ~1,000 employees, the Excel bulk import is usually faster and less error-prone than the API:
- Navigate to Global Settings > Data Import
- Select the entity (Employee Profile, Employee Job Details, Employee Address, etc.)
- Download the Excel template — it comes pre-populated with existing employees if updating
- Fill in the template with transformed greytHR data
- Upload, match columns, preview for errors, confirm
Keka validates the upload and surfaces errors before committing. Red-marked columns in the template indicate mandatory fields.
Using the Keka REST API
Keka's REST API uses OAuth 2.0 authentication. The token request requires client_id, client_secret, api_key, and scope=kekaapi. The access token has a 24-hour validity.
Authentication example:
POST https://{{your-domain}}.keka.com/connect/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=kekaapiRate limit: 50 requests per minute. Exceeding this returns a 429 error with rateLimitExceeded reason. The quota auto-refills after 60 seconds. Implement retry logic with exponential backoff starting at 60 seconds.
Key Keka API endpoints for migration use:
| Entity | Endpoint | Method | Notes |
|---|---|---|---|
| Create employee | /api/v1/hris/employees |
POST | Core profile only; requires legalEntityId, businessUnitId |
| Get employees | /api/v1/hris/employees?pageSize={n}&pageToken={token} |
GET | Max pageSize 200; use nextPageToken for pagination |
| Get employee by ID | /api/v1/hris/employees/{id} |
GET | Returns Keka internal ID |
| Update employee | /api/v1/hris/employees/{id} |
PUT | Full record replacement |
| Get departments | /api/v1/hris/departments |
GET | Use to verify org structure before employee import |
| Get locations | /api/v1/hris/locations |
GET | Validate location IDs before salary assignment |
| Upload document | /api/v1/hris/employees/{id}/documents |
POST | Multipart form; one file per request |
| Get leave balances | /api/v1/leave/employees/{id}/balances |
GET | Read only; balances set via import |
The employee create payload requires fields that the minimal example omits. A complete create request:
POST /api/v1/hris/employees
{
"firstName": "Rahul",
"lastName": "Sharma",
"displayName": "Rahul Sharma",
"gender": "Male",
"dateOfBirth": "1990-05-15T00:00:00Z",
"dateOfJoining": "2021-08-01T00:00:00Z",
"employeeNumber": "EMP-1042",
"legalEntityId": "le_abc123",
"businessUnitId": "bu_def456",
"departmentId": "dept_ghi789",
"locationId": "loc_jkl012",
"jobTitle": "Senior Backend Developer",
"reportingManagerEmployeeNumber": "EMP-0010"
}legalEntityId, businessUnitId, departmentId, and locationId are internal Keka UUIDs — retrieve them via the departments and locations GET endpoints before constructing your create payload. The API does not accept string names for these fields.
This endpoint creates the basic profile only. Statutory details, salary assignment, and YTD data require separate payroll-specific endpoints or the Excel import path. For document uploads, each file requires a separate POST call — at the 50 req/min ceiling, uploading 24,000 documents (2,000 employees × 12 monthly payslips) will take approximately 8 hours minimum. Plan accordingly.
For more on Keka's export capabilities, see How to Export Data from Keka: Methods, API Limits & Portability.
How to Handle Payroll in the Migration
Payroll is the hardest part of a greytHR to Keka migration. Both platforms are Indian payroll engines with statutory compliance, but they model salary structures differently.
The YTD TDS Problem: A Worked Example
The most consequential data migration requirement for a mid-year cutover is accurate YTD payroll data. Here is what happens if you get it wrong, with concrete numbers.
Scenario: Employee cutting over October 1st. Annual CTC ₹12,00,000. Old tax regime. Has declared ₹1,50,000 under Section 80C.
Correct YTD (April–September, 6 months) from greytHR:
| Component | Monthly | 6-Month Total |
|---|---|---|
| Gross Earnings | ₹1,00,000 | ₹6,00,000 |
| PF Employee Deduction | ₹1,800 | ₹10,800 |
| Professional Tax | ₹200 | ₹1,200 |
| TDS Deducted | ₹8,450 | ₹50,700 |
What Keka needs as YTD input: Total gross paid (₹6,00,000), total TDS already deducted (₹50,700), total PF deducted (₹10,800), and declared exemptions applied to date.
What happens if YTD is missing: Keka assumes no income was earned from April to September. It calculates TDS for the full year based only on the remaining 6 months of salary. For this employee, Keka would project annual income as ₹6,00,000 (6 months × ₹1,00,000) instead of ₹12,00,000. Taxable income after standard deduction (₹50,000) and 80C (₹1,50,000) drops to ₹4,00,000 — which falls entirely in the 5% slab. Keka calculates TDS for the remaining 6 months as approximately ₹7,500 total, rather than the correct ₹50,700 remaining.
Consequence: The employee is under-taxed by approximately ₹43,200 for the year. When Form 16 is generated, the mismatch surfaces as a liability for either the employer (if they absorb the shortfall) or the employee (if they owe at ITR filing time). Either outcome creates a compliance and employee relations problem.
The correct import: Load the YTD earnings, deductions, and TDS figures from the greytHR payroll register into Keka's YTD import template (Payroll > Payroll Admin > Operations > YTD Import). The template requires employee number, financial year, and month-wise breakdown of all earnings and deductions.
The Migration Path for Payroll
- Map greytHR salary components to Keka's component taxonomy. Keka has standard components (Basic, HRA, Special Allowance, PF Employer, ESI Employer, etc.) and allows custom components. Document every greytHR component and its Keka equivalent.
- Create salary structures (CTC templates) in Keka using the consolidation framework above — percentage-based splits, fixed amounts, slab-based calculations.
- Import tax declarations before salary assignment.
- Import employee salary data using Keka's payroll import templates: employee number, CTC amount, and per-component overrides where needed.
- Import YTD data for mid-year migrations. Load previous months' earnings and tax deductions so Keka calculates TDS correctly for the remaining year.
Statutory Data: PF, ESI, and Professional Tax
Statutory identifiers (UAN, PF number, ESI number) transfer directly — these are employee-level values. But the configuration around them (PF establishment code, ESI branch, contribution rates, voluntary PF elections) must be set up in Keka's pay group configuration before employee import.
Professional tax slabs are state-specific in both systems and must be configured in Keka based on employee work location. greytHR's automatic PT slab assignment does not carry over — you must re-configure this in Keka's compliance settings for each state where you have employees.
Leave Accrual Logic
greytHR handles leave accruals via backend formulas. Keka uses configurable Leave Policies. You do not migrate the formulas — you migrate the balances as of the cutover date, and configure Keka to handle future accruals. For each leave type, capture:
- Opening Balance
- Accrued (YTD)
- Consumed (YTD)
- Current Balance
How to Execute a Parallel Payroll Run
A direct cutover without a parallel run is exceptionally risky in Indian payroll due to the complexity of TDS, PF calculations, and varying month-day logic (e.g., calculating LOP based on 30 vs. 31 days).
Run both greytHR and Keka simultaneously for at least one full payroll cycle:
- Freeze greytHR: Stop all structural changes (new hires, salary revisions) on the 20th of the month.
- Extract and Load: Move all data into Keka by the 25th.
- Process Both Systems: Run the payroll engine in both greytHR and Keka for that month.
- Reconcile: Export the gross-to-net payroll register from both systems. Compare them using a script or VLOOKUP on the Employee ID.
Common Parallel Run Mismatches
You will almost certainly find discrepancies. The most common causes:
- LOP (Loss of Pay) calculations: greytHR might calculate daily wage by dividing monthly basic by actual days in the month (e.g., 31), while Keka might be configured to use a fixed 30-day denominator. Verify the Pay Group settings in Keka. For an employee with ₹40,000 basic on LOP for 2 days in a 31-day month, the difference is ₹2,581 (31-day basis) vs. ₹2,667 (30-day basis) — a ₹86 discrepancy per employee per LOP day that compounds across headcount.
- PF rounding rules: greytHR and Keka may apply different rounding rules (rounding to the nearest rupee vs. rounding up). This typically results in a ₹1–2 difference in net pay per employee. Acceptable, but must be documented for your finance team.
- Professional Tax state mapping: PT slabs vary by state. Ensure Keka has the correct state mapped to the employee's location.
- TDS variations: If YTD data or tax declarations (Section 80C, 80D) were not mapped perfectly, Keka's projected tax will differ from greytHR's. Verify investment declarations imported into Keka match source data.
- Salary component rounding at the paisa level: Sub-rupee differences propagate across every employee, every month. Document your rounding rules and verify during the parallel run.
Validation Checklist
Do not go live until you have verified each of these:
- Employee headcount match. Total active employees in Keka equals greytHR source count.
- Reporting structure integrity. Every employee's reporting manager resolves correctly in Keka's org tree.
- Statutory identifiers. UAN, PF number, ESI number match for every employee.
- Bank details. Account numbers and IFSC codes verified against source — one wrong digit means a failed salary transfer.
- Leave balance accuracy. Opening balances in Keka match greytHR's closing balances at cutover date.
- Tax declarations loaded. Section 80C/80D declarations verified for all employees before payroll unlock.
- Salary structure validation. Parallel run comparison of gross, deductions, net pay, PF employer, ESI employer, and PT for every employee.
- Document completeness. Spot-check a random sample (minimum 10%) for uploaded documents.
- Self-service portal access. Employees can log in to Keka, view their profile, and see correct data.
Rollback Procedure
No migration guide for a payroll system should omit what to do when the migration fails mid-process. Define your rollback trigger threshold before starting: a reasonable threshold is more than 2% of employees with gross pay variance greater than ₹500, or any employee with a statutory identifier mismatch.
If the parallel run fails to reconcile within acceptable margins:
- Do not close greytHR. Keep greytHR active and process the month's payroll in greytHR as planned. Employees are paid correctly; only the Keka data is affected.
- Identify root cause before re-attempting. Common root causes: incorrect YTD import, pay group misconfiguration, or salary structure percentage errors. Each has a different fix path.
- For YTD errors: Delete and re-import YTD data in Keka. YTD data does not affect employee master records or salary structures — it can be replaced without cascading effects.
- For salary structure errors: If the structure itself is wrong (wrong percentages, wrong components), you can edit the structure in Keka and reprocess. This does not trigger the pay group destruction problem — only pay group reassignment at the employee level does.
- For pay group errors: This is the most damaging scenario. If employees were assigned to the wrong pay group, you must reassign them (destroying payroll data), then re-enter salary data and YTD figures. Prioritize correcting the configuration before re-importing employees.
- Reset timeline: Allow one additional payroll cycle for re-validation before attempting the live cutover.
The pay group destruction scenario has no automated recovery. If you discover that 50 employees were assigned to the wrong pay group post-import, you are facing manual re-entry for each employee's salary, statutory details, and YTD data. This is why pay group configuration is Step 3 in the load sequence and why dry-run imports in a test environment against Keka's sandbox are non-negotiable before production loads.
Handling Historical Documents
Migrating historical payslips and tax documents (Form 16) is a common requirement for compliance and employee experience. greytHR exports these as PDFs, and Keka requires them attached to specific employee records.
Create matching document categories in Keka before uploading. greytHR's categories (Aadhaar, PAN, offer letter, etc.) may not map 1:1 to Keka's taxonomy.
For scripted migration, write a script that:
- Parses the filename of the greytHR export (e.g.,
EMP-1042_Payslip_Aug2023.pdf) - Extracts the Employee ID (
EMP-1042) - Queries the Keka API to find the internal Keka UUID for that employee (
GET /api/v1/hris/employees?employeeNumber=EMP-1042) - Uses Keka's document upload endpoint (
POST /api/v1/hris/employees/{id}/documents) to push the file to the correct employee folder as multipart form data
Keka also supports folder-based batch uploads in the Employee Documents section, which can be faster for large volumes if you organize files by employee beforehand.
If your migration includes sensitive compensation data, ensure extraction and transformation scripts run in a secure, compliant environment. Avoid storing flat files on local developer machines. Review How to Safely Migrate Sensitive Employee & Payroll Data for infrastructure best practices.
How Long Does a greytHR to Keka Migration Take?
A typical migration takes 2–6 weeks for organizations with 100–1,000 employees, depending on payroll structure complexity and historical data volume.
| Factor | Timeline Impact |
|---|---|
| Employee count < 200 | 1–2 weeks for core data |
| Employee count 200–1,000 | 2–4 weeks |
| Complex salary structures (10+ components, multiple pay groups) | Add 1–2 weeks |
| Historical payroll document transfer | Add 1 week |
| Multi-location statutory compliance setup | Add 1 week |
| Multi-entity migration (separate legal entities) | Add 1–2 weeks |
| Parallel payroll run + validation | 1 pay cycle (typically 1 month) |
The parallel payroll run is the bottleneck. You can complete the data migration in days, but validating payroll accuracy takes a full cycle.
Choosing the Right Migration Window
The best time to cut over is at the start of a new financial year (April 1) or at a quarter boundary (July 1, October 1, January 1). This simplifies:
- Form 16 generation. The full financial year's data lives in one system, not split across two.
- PF and ESI filing. Monthly returns are cleaner when a single system owns the entire quarter.
- Leave balance carryover. Year-start is a natural reset point for most leave policies.
- YTD complexity. An April 1 cutover eliminates the YTD import problem entirely — Keka starts with a clean slate for the financial year.
Mid-month or mid-quarter cutovers are possible but create reconciliation overhead — you will need to manually stitch payroll data across two systems for compliance filings.
Common Failure Modes
These patterns consistently cause problems in greytHR-to-Keka migrations:
- Importing employees before org structure is finalized. Keka validates department, location, and legal entity references on import. If these don't exist, the import fails row by row.
- Mismatched employee numbers. If greytHR employee numbers contain characters or formats that Keka doesn't accept, the import silently mismatches or fails. Validate format compatibility upfront.
- Date format mismatches. greytHR exports dates in DD-MM-YYYY (common in Indian locale); Keka's import templates may expect different formats depending on the template version. Standardize on the format shown in the downloaded Keka template.
- Pay group assignment errors. Reassigning a pay group after employee creation destroys all payroll data for that employee. There is no undo.
- Missing LOP data. If an employee had LOP deductions in greytHR and this isn't accounted for in their Keka profile, the first Keka payroll run will over-pay or under-pay them. Carry forward LOP balances explicitly.
- Document category mismatch. greytHR's document categories may not map 1:1 to Keka's taxonomy. Create matching categories before bulk upload.
- Dummy statutory data. greytHR sometimes allows placeholder values like "NOT APPLICABLE" for PAN or Aadhar in older records. Keka's validators will reject these, failing the entire row.
- Missing tax declarations. Failing to import Section 80C/80D declarations before the first payroll run causes TDS overcollection that must be corrected retroactively. Harder to fix than getting it right at import time.
- Incomplete multi-entity configuration. Organizations with multiple legal entities must create separate Pay Groups and statutory configurations per entity. Employees cannot cross entity boundaries within a single Pay Group.
Finalizing the Cutover
Once the parallel run reconciles within acceptable margins — zero variance for gross pay, less than ₹5 for rounding differences in statutory deductions — you are ready for the final cutover.
Lock greytHR to read-only access. Direct all employees to Keka for leave applications and attendance tracking. Keep greytHR active for at least one financial quarter — you will need it for generating Form 16 for the period processed in greytHR, responding to PF/ESI audits referencing historical data, and as a fallback if discrepancies surface in Keka during the first few cycles. After that quarter, decommission greytHR entirely.
When to Bring in Help
A greytHR to Keka migration is technically feasible for an in-house HR or IT team for organizations under 200 employees with simple salary structures (three or fewer component patterns, single legal entity, single state for PT). It gets significantly harder when:
- You have 500+ employees across multiple legal entities
- Salary structures include complex variable components, performance-linked pay, or multi-state professional tax
- You need to migrate historical payroll documents at scale (10,000+ files)
- Your greytHR instance has heavy customization in attendance or leave policies
- A mid-year cutover means YTD data must be precisely loaded for TDS accuracy
- You cannot afford payroll errors during the transition — even small ones
This is the kind of migration we handle at ClonePartner. We write custom extraction scripts against greytHR's API, build the transformation layer to match Keka's data model, and run the entire load sequence with validation checks at each stage.
Frequently Asked Questions
- Can I migrate YTD payroll data from greytHR to Keka mid-year?
- Yes. You must extract the YTD Payroll Register from greytHR (via the salary statement API or Reports Gallery) and import it into Keka before running your first payroll. This ensures Keka's engine calculates Tax Deducted at Source (TDS) correctly for the remainder of the financial year.
- Can I export all my data from greytHR at once?
- No. greytHR has no single 'Export All' function. You need to combine REST API v2 extraction (employees, leave, attendance, payroll), Query Builder reports (custom Excel exports), and the Reports Gallery (PDF/XLS downloads) to get a complete data set. Documents require per-employee, per-category API calls.
- What is Keka's API rate limit?
- Keka enforces a rate limit of 50 API requests per minute. Exceeding this returns a 429 error with 'rateLimitExceeded' reason. The quota auto-refills after 60 seconds. The default pagination size is 100 records per page, with a maximum of 200.
- How long does a greytHR to Keka migration take?
- Typically 2–6 weeks for 100–1,000 employees. The data migration itself can be completed in days, but a parallel payroll run — processing one month in both systems simultaneously and comparing results — takes a full pay cycle and is the real bottleneck.
- When is the best time to migrate from greytHR to Keka?
- The start of a financial year (April 1) or a quarter boundary (July 1, October 1, January 1). This avoids splitting Form 16 data and PF/ESI filings across two systems, and aligns with natural leave balance reset points.