Skip to content
Embedded Benefits
Concepts

Census Sync

How to submit employee data in bulk via census sync, monitor async processing, and handle validation errors.

Census sync replaces an employer’s entire employee roster. When you submit a new sync, the system matches existing employees using reference_id and other available information. Employees included in the payload are created or updated; employees omitted are deactivated. This is not an append operation.

You send a single POST /v1/employers/{id}/census-sync request containing up to 5,000 employees, and Vitable processes them asynchronously. The response is an acceptance receipt — not the final result. You track outcomes through webhooks and the GET /v1/employers/{id}/employees endpoint.

This guide covers the request format, the async processing model, how to verify results, and what to do when things go wrong.

FieldTypeRequiredRules
first_namestringYes
last_namestringYes
date_of_birthstringYesISO 8601 date
emailstringYesValid email address
phonestringYes10-digit US phone number
reference_idstringNoMust be unique within the payload
address.address_line_1stringNo
address.address_line_2stringNo
address.citystringNo
address.statestringNoValid US state or territory code
address.zipcodestringNo
start_datestringNoISO 8601 date
employee_classstringNoFull Time, Part Time, Temporary, Intern, Seasonal, Individual Contractor
compensation_typestringNoSalary or Hourly
RuleLimit
Maximum employees per request5,000
reference_id uniquenessMust be unique within a single payload
phone format10-digit US number
state formatValid US state or territory code

Census sync is fully asynchronous. When you submit a request, Vitable validates the payload structure and immediately returns an acceptance receipt. The actual employee creation and eligibility evaluation happen in the background.

sequenceDiagram
    participant P as Partner
    participant V as Vitable API
    P->>V: POST /v1/employers/{id}/census-sync
    V-->>P: 202 { data: { accepted_at, employer_id } }
    Note over V: Async processing begins
    V--)P: webhook: employee.eligibility_granted (per employee)
    P->>V: GET /v1/employers/{id}/employees
    V-->>P: 200 Paginated employee list

Flow summary:

  1. You submit a POST /v1/employers/{id}/census-sync request with an array of employees.
  2. Vitable responds with 202 and an acceptance receipt containing accepted_at and employer_id.
  3. Vitable processes each employee asynchronously — creating records and evaluating eligibility.
  4. For each employee that becomes benefits-eligible, Vitable delivers an employee.eligibility_granted webhook.
  5. You verify the final state by calling GET /v1/employers/{id}/employees.

Send a POST /v1/employers/{id}/census-sync request with an employees array:

{
"employees": [
{
"reference_id": "EMP-001",
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1990-05-15",
"email": "jane.doe@example.com",
"phone": "5551234567",
"address": {
"address_line_1": "123 Main St",
"address_line_2": "Apt 4B",
"city": "Austin",
"state": "TX",
"zipcode": "78701"
},
"start_date": "2026-01-15",
"employee_class": "Full Time",
"compensation_type": "Salary"
},
{
"reference_id": "EMP-002",
"first_name": "John",
"last_name": "Smith",
"date_of_birth": "1985-11-22",
"email": "john.smith@example.com",
"phone": "5559876543",
"address": {
"address_line_1": "456 Oak Ave",
"city": "Dallas",
"state": "TX",
"zipcode": "75201"
},
"start_date": "2026-02-01",
"employee_class": "Part Time",
"compensation_type": "Hourly"
}
]
}

A successful response looks like this:

{
"data": {
"accepted_at": "2026-03-25T14:30:00+00:00",
"employer_id": "empr_550e8400-e29b-41d4-a716-446655440000"
}
}

The accepted_at timestamp marks when Vitable acknowledged the request. Store this alongside the employer_id so you can correlate it with incoming webhooks.

The system matches employees using reference_id and other available information to preserve existing records and enrollment history across syncs. Matched employees are updated with the new data; unmatched entries create new employee records.

Previously deactivated employees are reactivated if they reappear in a subsequent sync.

Required fields per employee: first_name, last_name, date_of_birth, email, phone

Optional fields: reference_id, address, start_date, employee_class, compensation_type

After submitting a census sync, you have two ways to track what happened: webhooks and the list employees endpoint.

As Vitable processes each employee, it evaluates eligibility based on the employer’s eligibility policy. When an employee becomes benefits-eligible, you receive an employee.eligibility_granted webhook:

{
"event_id": "wevt_550e8400-e29b-41d4-a716-446655440000",
"organization_id": "org_xyz789",
"event_name": "employee.eligibility_granted",
"resource_type": "employee",
"resource_id": "empl_7c9e6679-7425-40de-944b-e07fc1f90ae7",
"created_at": "2026-03-25T14:31:00+00:00"
}

Use the resource_id to fetch the employee’s full record via GET /v1/employees/{id}.

You can also poll GET /v1/employers/{id}/employees to see which employees have been created. This endpoint returns a paginated list:

Terminal window
GET /v1/employers/{id}/employees?page=1&limit=20
ParameterDefaultDescription
page1Page number
limit20Number of employees per page

The response includes pagination metadata:

{
"data": [...],
"pagination": {
"page": 1,
"limit": 20,
"total": 150,
"total_pages": 8
}
}

Compare pagination.total against the number of employees you submitted to confirm all records were created.

This diagram shows the complete sequence for a successful census sync, from submission through employee verification.

sequenceDiagram
    participant P as Partner
    participant V as Vitable API
    P->>V: POST /v1/employers/{id}/census-sync (N employees)
    V-->>P: 202 { data: { accepted_at, employer_id } }
    Note over V: Processing employee 1 of N
    V--)P: webhook: employee.eligibility_granted (employee 1)
    Note over V: Processing employee 2 of N
    V--)P: webhook: employee.eligibility_granted (employee 2)
    Note over V: ... (remaining employees)
    P->>V: GET /v1/employers/{id}/employees?page=1&limit=20
    V-->>P: 200 Paginated employee list (total: N)

Step-by-step:

  1. You send a census sync with N employees.
  2. Vitable returns the acceptance receipt immediately.
  3. For each processed employee, Vitable delivers an employee.eligibility_granted webhook (timing depends on the employer’s eligibility policy and any waiting period).
  4. You call the list employees endpoint to confirm all N records exist.

Not every census sync succeeds cleanly. The following flowchart shows how validation and processing errors surface.

sequenceDiagram
    participant P as Partner
    participant V as Vitable API
    P->>V: POST /v1/employers/{id}/census-sync
    alt Payload invalid
        V-->>P: 400 Validation Error (no processing)
    else Payload valid
        V-->>P: 202 Accepted
        Note over V: Per-employee async processing
        V--)P: webhook: employee.eligibility_granted (valid employees)
    end

Summary:

  • If the payload structure is invalid (e.g., missing required fields, exceeding 5,000 employees), you receive a 400 error immediately — no processing occurs.
  • If the payload is accepted, individual employees may still fail during async processing (e.g., a duplicate reference_id matching an existing employee). Successfully processed employees are created; failed ones are skipped.
  • You will only receive employee.eligibility_granted webhooks for employees that were successfully created and evaluated as eligible.

Each census sync request accepts a maximum of 5,000 employees. If your payload exceeds this limit, the entire request is rejected with a 400 error. Split larger datasets into multiple requests.

Duplicate reference_id values within a payload

Section titled “Duplicate reference_id values within a payload”

Every reference_id in a single request must be unique. If you include the same reference_id twice, the request fails validation. Deduplicate your data before submitting.

The phone field must be a 10-digit US phone number (digits only, no dashes or spaces). Values like 555-123-4567 or +15551234567 are rejected. Send 5551234567 instead.

The state field must be a valid US state or territory code (e.g., TX, CA, PR). Full state names like Texas are not accepted.

When some employees in a batch are valid and others are not, Vitable processes the valid ones and skips the invalid ones. You will not receive an explicit error notification for skipped employees. To detect partial failures, compare the pagination.total from GET /v1/employers/{id}/employees against the number of employees you submitted. If the count is lower than expected, review your source data for the issues described above and resubmit the corrected records.

EventDescription
employee.eligibility_grantedAn employee has been evaluated as eligible for benefits. View event details