Kuali GraphQL Documentation

Guides

Bulk import an HR feed

Bulk-import your institution's people and organizational units from a Classic HR feed (or a JSON groups batch).


Overview

POST /api/v0/imports/hr-feed/people accepts an unmodified Classic hrmanifest document (schema version 2.0) and treats it as the authoritative active roster: people are created or updated, and (once a later run omits them) deactivated. The feed carries 90 attributes; only the 12 below are ever read. Everything else is accepted and discarded at parse time — it is never stored, logged, or reported on.

Imported fields

Attribute Element Destination
principalId record institutional ID
principalName record username
active record active
affiliationType affiliation affiliation
firstName name first name
middleName name middle name
lastName name last name
prefix name prefix
suffix name suffix
title name title
emailAddress email email
phoneNumber phone phone

Which row is imported

A person can carry more than one <name>, <email>, or <phone>. At most one row per element is imported.

  • Name and email: the first row in the document. nameCode, emailType, and the default and active flags are not imported and do not affect the choice, so put the row you want applied first.
  • Phone: the first row with phoneType="WRK". The number is stored as the person's phone. A record whose only numbers are FAX, HM, MBL, or OTH leaves the phone unset — those numbers have no destination on the person record.
  • No qualifying row leaves the destination unset. It is never an error.

Limits

  • 250 MB and 100,000 records per submission
  • one roster import per institution at a time
  • results are retained 90 days

Ignored fields

Every other Classic attribute is accepted but never stored, logged, or reported. This is enforced at the XML parser itself, not by later filtering.

Attribute Element
statusEmailRecipient hrmanifest
reportDate hrmanifest
entityId record
campus affiliation
default affiliation
active affiliation
employeeStatus employment
employeeType employment
baseSalaryAmount employment
primaryDepartment employment
employeeId employment
primaryEmployment employment
addressTypeCode address
addressLine1 address
addressLine2 address
addressLine3 address
city address
stateOrProvince address
postalCode address
country address
default address
active address
nameCode name
default name
active name
phoneType phone
extension phone
country phone
default phone
active phone
emailType email
default email
active email
citizenshipType kcExtendedAttributes
county kcExtendedAttributes
ageByFiscalYear kcExtendedAttributes
race kcExtendedAttributes
educationLevel kcExtendedAttributes
degree kcExtendedAttributes
major kcExtendedAttributes
handicapped kcExtendedAttributes
handicapType kcExtendedAttributes
veteran kcExtendedAttributes
veteranType kcExtendedAttributes
visa kcExtendedAttributes
visaType kcExtendedAttributes
visaCode kcExtendedAttributes
visaRenewalDate kcExtendedAttributes
officeLocation kcExtendedAttributes
secondaryOfficeLocation kcExtendedAttributes
school kcExtendedAttributes
yearGraduated kcExtendedAttributes
directoryDepartment kcExtendedAttributes
directoryTitle kcExtendedAttributes
primaryTitle kcExtendedAttributes
vacationAccrual kcExtendedAttributes
onSabbatical kcExtendedAttributes
idProvided kcExtendedAttributes
idVerified kcExtendedAttributes
multiCampusPrincipalId kcExtendedAttributes
multiCampusPrincipalName kcExtendedAttributes
salaryAnniversaryDate kcExtendedAttributes
degreeCode degree
degree degree
graduationYear degree
fieldOfStudy degree
specialization degree
school degree
schoolId degree
schoolIdCode degree
unitNumber appointment
jobCode appointment
appointmentType appointment
salary appointment
startDate appointment
endDate appointment
jobTitle appointment
preferedJobTitle appointment

Run statuses

A run reports accepted, validating, applying, or sweeping while it is still working, and finishes in one of:

  • completed — every record applied and the sweep ran clean
  • completed_with_failures — the run finished, but at least one record failed or a deactivation did
  • completed_deactivations_withheld — applied, but the deactivation sweep exceeded its threshold and is waiting on your confirmation
  • completed_deactivations_refused, completed_deactivations_stale — the sweep was refused outright, or the approved candidate set had drifted by the time you confirmed it
  • failed — the run stopped and will not resume; failure.error and failure.message say why. How much applied depends on the cause: a rejected payload means nothing did, but a sweep failure happens only after every record already landed — the deactivation pass is what failed, not the roster
  • failed_dependency_unavailable — attribute writes failed consecutively past the configured threshold, so the run halted instead of failing every remaining record one at a time. Within counts.processed, records from chunks completed before the halt applied fully and resubmitting re-applies them as no-ops; the halting chunk's own failing records had their person data applied but not their attributes, so resubmitting re-attempts just those writes. The streak can come from either of two different causes — the destination page (or its reference data) being unreachable, or a value the destination keeps rejecting on every record — so check the run's failure.message and the per-record results to see which one it was before resubmitting

Per-record failure reasons

GET /api/v0/imports/:runId/results streams one outcome line per submitted record. Every line also carries attributeswritten, unchanged, skipped, or failed, this record's own attribute-write outcome — and a warnings list of field/value/reason entries for this record's own attributes; a run-level warning is never on a per-record line, only on the run itself. A failed record names one of:

  • missing_required_field — a required imported attribute was blank or absent
  • invalid_value — a supplied value didn't match its required pattern
  • duplicate_in_payload — the same institutional ID appeared twice in this submission
  • held_by_other_person — the username is already assigned to a different person
  • ambiguous_institutional_id — two existing people already hold this institutional ID
  • identity_rejected — the record failed a save-time validation not listed above
  • dependency_unavailable — the person was applied but their attribute write failed after retries
  • section_create_rejected — the person's attribute section document could not be created
  • validation_rejected — the attribute write failed a save-time field validation on the section document
  • write_rejected — the attribute section document write failed for another reason
  • unit_number_field_disabled, parent_not_found, parent_cycle — group-batch specific