Back to guides

HRIS Integration

Sync employee data for targeted survey distribution

The HRIS (Human Resource Information System) integration allows you to sync employee data from systems like Workday, BambooHR, or your own HR database. This enables targeted survey distribution based on department, location, tenure, and custom attributes.

Bulk Import

Import thousands of respondents at once

Incremental Sync

Keep data up-to-date with delta syncs

Smart Targeting

Target surveys by any attribute

Respondent Data Model

Each respondent can include standard HR fields plus custom attributes for targeting:

{
  "externalId": "emp-12345",        // Your HRIS employee ID (required)
  "email": "jane.doe@company.com",  // Email address (required)
  "firstName": "Jane",
  "lastName": "Doe",
  "department": "Engineering",
  "location": "San Francisco",
  "jobTitle": "Senior Engineer",
  "managerId": "emp-67890",         // For org hierarchy
  "hireDate": "2023-03-15",
  "employmentType": "full-time",
  "attributes": {                   // Custom attributes for targeting
    "team": "Platform",
    "level": "L5",
    "region": "West",
    "costCenter": "CC-1234"
  }
}

Sync API

Use the sync endpoint to import or update respondents. The sync is idempotent based on externalId.

Request

POST /api/v1/respondents/sync
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "mode": "upsert",           // "upsert" | "replace" | "append"
  "respondents": [
    {
      "externalId": "emp-12345",
      "email": "jane.doe@company.com",
      "firstName": "Jane",
      "lastName": "Doe",
      "department": "Engineering",
      "location": "San Francisco",
      "attributes": {
        "team": "Platform",
        "level": "L5"
      }
    },
    {
      "externalId": "emp-12346",
      "email": "john.smith@company.com",
      "firstName": "John",
      "lastName": "Smith",
      "department": "Marketing",
      "location": "New York"
    }
  ]
}

Response

{
  "data": {
    "jobId": "sync_abc123def456",
    "status": "processing",
    "totalRecords": 2,
    "estimatedCompletionTime": "2026-02-04T10:35:00Z"
  },
  "meta": {
    "requestId": "req_xyz789",
    "timestamp": "2026-02-04T10:30:00Z",
    "apiVersion": "v1"
  }
}

Sync Modes

ModeBehaviorUse Case
upsertInsert new records, update existing by externalIdIncremental daily syncs
replaceDelete all existing, insert new recordsFull refresh from HRIS
appendOnly insert new records, skip existingAdding new hires only

Tracking Sync Progress

Large syncs run asynchronously. Poll the job status endpoint to track progress:

GET /api/v1/respondents/sync/sync_abc123def456
Authorization: Bearer YOUR_API_KEY

// Response
{
  "data": {
    "jobId": "sync_abc123def456",
    "status": "completed",        // pending | processing | completed | failed
    "progress": 100,
    "stats": {
      "totalRecords": 5000,
      "created": 4500,
      "updated": 450,
      "skipped": 50,
      "errors": 0
    },
    "startedAt": "2026-02-04T10:30:00Z",
    "completedAt": "2026-02-04T10:32:15Z"
  }
}

Processing Time

Sync jobs process approximately 1,000 records per second. Large imports (10,000+ records) may take several minutes.

Targeting Surveys

Once respondents are synced, you can target surveys using any field or custom attribute:

POST /api/v1/surveys/{surveyId}/distribute
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "targeting": {
    "filters": [
      { "field": "department", "operator": "in", "value": ["Engineering", "Product"] },
      { "field": "location", "operator": "equals", "value": "San Francisco" },
      { "field": "attributes.level", "operator": "gte", "value": "L4" }
    ],
    "logic": "AND"               // "AND" | "OR"
  },
  "distribution": {
    "method": "email",           // "email" | "link" | "embed"
    "schedule": "2026-02-05T09:00:00Z",
    "reminder": {
      "enabled": true,
      "afterDays": 3
    }
  }
}

Filter Operators

OperatorDescriptionExample
equalsExact matchdepartment equals "Engineering"
inMatch any in arraylocation in ["NYC", "SF"]
containsString containsjobTitle contains "Manager"
gte / lteGreater/less than or equalhireDate gte "2023-01-01"
existsField has valuemanagerId exists true

Best Practices

Use stable external IDs

Use your HRIS employee ID as the externalId to ensure consistent updates across syncs.

Schedule daily incremental syncs

Run upsert syncs daily to capture new hires, terminations, and data changes automatically.

Normalize attribute values

Ensure consistent values (e.g., "Engineering" not "Eng" or "engineering") for reliable targeting.

Handle terminated employees

Use replace mode monthly or add a "status" attribute to filter out terminated employees from surveys.

Required Scopes

  • respondents:writeCreate and update respondents
  • respondents:syncRun sync jobs
  • respondents:readView respondent data and job status