Skip to content

Data Model Reference

This page documents the fields available for each entity type in Custom Integrations.

For PULL hooks, these are the fields you include in the data object of each record. For PUSH hooks, these are the fields available on ctx.event.before and ctx.event.after.

Common patterns

  • externalId — Required in PULL records. This is your external system's unique identifier for the record. Flowstate uses it to match records across syncs.
  • Dates — Use ISO 8601 format: YYYY-MM-DD (e.g., 2025-06-15).
  • Custom attributes — All entity types support a customAttributes object for arbitrary key-value data. See Custom attributes.

Employee

FieldTypeRequiredDescription
firstNamestringYesEmployee's first name
lastNamestringYesEmployee's last name
emailstringYesWork email address
internalEmployeeIdstringNoYour internal employee identifier (e.g., payroll number)
startDatestring (date)NoEmployment start date
endDatestring (date)NoEmployment end date (for terminated employees)
jobRoleobject or stringNoRole the employee holds. See Job role.
teamAllocationsarrayNoSee Team allocations
projectAllocationsarrayNoSee Project allocations
salaryAdjustmentsarrayNoSee Salary adjustments
customAttributesobjectNoSee Custom attributes
js
{
  externalId: 'emp-001',
  data: {
    firstName: 'Jane',
    lastName: 'Smith',
    email: 'jane.smith@example.com',
    internalEmployeeId: 'EMP-2024-042',
    startDate: '2024-03-15',
    jobRole: { title: 'Senior Engineer', externalId: 'ROLE-042' },
    teamAllocations: [
      { teamId: 'team-042', teamName: 'Platform', startDate: '2024-03-15', fte: 1.0 }
    ]
  }
}

Vacancy

FieldTypeRequiredDescription
rolestringYesJob title or role name
descriptionstringNoRole description
statusstringNoVacancy status (defaults to open)
ftenumberNoFull-time equivalent value (defaults to 1.0)
targetStartDatestring (date)NoIntended start date for the hire
targetFillDatestring (date)NoTarget date to fill the vacancy
salaryMinnumberNoMinimum salary for the role
salaryMaxnumberNoMaximum salary for the role
currencyCodestringNoISO 4217 currency code for salary values (e.g., GBP, USD)
jobRoleobject or stringNoRole the vacancy is hiring for. See Job role.
teamAllocationsarrayNoSee Team allocations
projectAllocationsarrayNoSee Project allocations
customAttributesobjectNoSee Custom attributes
js
{
  externalId: 'vac-101',
  data: {
    role: 'Senior Software Engineer',
    description: 'Backend systems team',
    status: 'open',
    fte: 1.0,
    targetStartDate: '2025-09-01',
    salaryMin: 85000,
    salaryMax: 110000,
    currencyCode: 'GBP',
    jobRole: { title: 'Senior Engineer', externalId: 'ROLE-042' }
  }
}

Contractor

FieldTypeRequiredDescription
namestringYesContractor or company name
emailstringNoContact email address
contractorTypestringNoindividual or company (defaults to individual)
rateTypestringNohourly, daily, or monthly
ratenumberNoCompensation rate
currencyCodestringNoISO 4217 currency code for rate (e.g., GBP, USD)
startDatestring (date)NoContract start date
endDatestring (date)NoContract end date
teamAllocationsarrayNoSee Team allocations
projectAllocationsarrayNoSee Project allocations
customAttributesobjectNoSee Custom attributes
js
{
  externalId: 'ctr-050',
  data: {
    name: 'Acme Consulting Ltd',
    email: 'billing@acme-consulting.com',
    contractorType: 'company',
    rateType: 'daily',
    rate: 750,
    currencyCode: 'GBP',
    startDate: '2025-01-06',
    endDate: '2025-06-30'
  }
}

Project

FieldTypeRequiredDescription
namestringYesProject name
descriptionstringNoProject description
projectCodestringNoInternal project code or reference
startDatestring (date)NoProject start date
endDatestring (date)NoProject end date
estimatedCostnumberNoEstimated total cost
prioritynumberNoPriority ranking (defaults to 0)
customAttributesobjectNoSee Custom attributes
js
{
  externalId: 'proj-alpha',
  data: {
    name: 'Platform Migration',
    description: 'Migrate core services to new infrastructure',
    projectCode: 'PLAT-2025',
    startDate: '2025-04-01',
    endDate: '2025-12-31',
    estimatedCost: 500000,
    priority: 1
  }
}

Assignment

Assignments link employees to projects. Both employeeSourceId and projectSourceId reference the externalId values you used when syncing the corresponding employee and project records.

FieldTypeRequiredDescription
employeeSourceIdstringYesThe externalId of the employee
projectSourceIdstringYesThe externalId of the project
ftenumberNoFTE allocation (defaults to 1.0)
startDatestring (date)NoAssignment start date
endDatestring (date)NoAssignment end date
js
{
  externalId: 'assign-001',
  data: {
    employeeSourceId: 'emp-001',
    projectSourceId: 'proj-alpha',
    fte: 0.5,
    startDate: '2025-04-01',
    endDate: '2025-12-31'
  }
}

TIP

Assignments require that both the employee and the project have already been synced via PULL hooks using the same integration. The employeeSourceId and projectSourceId are matched against existing records by their externalId.

Team allocations

Nested inside an Employee, Vacancy, or Contractor record as teamAllocations. Each entry places the parent on a team over a time range. Teams are auto-created when neither teamId nor an existing name matches.

FieldTypeRequiredDescription
teamIdstringNo*External system's team identifier. Preferred over teamName for stability.
teamNamestringNo*Team display name. Used to look up or auto-create the team if teamId is not provided.
startDatestring (date)NoAllocation start date (ISO 8601). Defaults to today.
endDatestring (date)NoAllocation end date. Omit or set null for open-ended.
ftenumberNoFTE allocation (0.0–1.0). Defaults to 1.0.

*At least one of teamId or teamName must be provided.

js
{
  externalId: 'emp-001',
  data: {
    firstName: 'Jane',
    lastName: 'Smith',
    email: 'jane.smith@example.com',
    teamAllocations: [
      { teamId: 'team-042', teamName: 'Platform', startDate: '2024-03-15', fte: 0.8 },
      { teamId: 'team-099', teamName: 'On-call rota', startDate: '2024-03-15', fte: 0.2 }
    ]
  }
}

Re-running a sync with the same (employee, team, startDate) is idempotent — duplicates are skipped.

Legacy aliases

teamAssignments (with externalTeamId, fromDate, toDate) is still accepted for backward compatibility with older hooks. New hooks should use the canonical names above.

Project allocations

Nested inside an Employee, Vacancy, or Contractor record as projectAllocations. Each entry places the parent on a project over a time range. Projects are auto-created when neither projectId nor an existing name matches.

FieldTypeRequiredDescription
projectIdstringNo*External system's project identifier. Preferred over projectName for stability.
projectNamestringNo*Project display name. Used to look up or auto-create the project if projectId is not provided.
startDatestring (date)NoAllocation start date (ISO 8601). Defaults to today.
endDatestring (date)NoAllocation end date. Omit or set null for open-ended.
ftenumberNoFTE allocation (0.0–1.0). Defaults to 1.0.

*At least one of projectId or projectName must be provided.

js
{
  externalId: 'emp-001',
  data: {
    firstName: 'Jane',
    lastName: 'Smith',
    email: 'jane.smith@example.com',
    projectAllocations: [
      { projectId: 'proj-alpha', projectName: 'Platform Migration', startDate: '2025-04-01', endDate: '2025-12-31', fte: 0.5 }
    ]
  }
}

Legacy aliases

projectAssignments (with externalProjectId, fromDate, toDate) is still accepted for backward compatibility with older hooks. New hooks should use the canonical names above.

When to use nested allocations vs the top-level Assignment entity

Use nested teamAllocations / projectAllocations to sync an employee and their allocations in a single record. Use the top-level Assignment entity when employees and projects are synced separately and you want to link them afterwards by externalId.

Salary adjustments

Nested inside an Employee record as salaryAdjustments. Each entry is a dated salary change. Deduplicated by (employee, effectiveDate) so re-running a sync is safe.

FieldTypeRequiredDescription
effectiveDatestring (date)YesDate the new salary takes effect (ISO 8601).
salarynumberYesAnnualised salary amount.
currencyCodestringYesISO 4217 currency code (e.g., GBP, USD).
bonusnumberNoOptional annual bonus amount.
reasonstringNoFree-text reason for the change (e.g., "promotion").

Entries missing any required field are silently skipped.

Job role

Nested inside an Employee or Vacancy record as jobRole. Accepts either an object with title and/or externalId, or a bare string (shorthand for { title: "…" }). Omit the field to leave the role unchanged on updates.

FieldTypeRequiredDescription
titlestringNo*Role name (e.g., 'Senior Engineer'). Used for lookup by name and for auto-creation when no match exists.
externalIdstringNo*Your external system's identifier for the role. Preferred over title for stability.

*At least one of title or externalId must be provided.

js
{
  externalId: 'emp-001',
  data: {
    firstName: 'Jane',
    lastName: 'Smith',
    email: 'jane@example.com',
    jobRole: { title: 'Senior Engineer', externalId: 'ROLE-042' }
  }
}

Resolution order:

  1. Match by externalId (scoped to your organisation).
  2. Fall back to matching by title (the role's name). If the matched role has no externalId yet and you supplied one, Flowstate patches it so subsequent syncs deduplicate correctly.
  3. Auto-create a new role using title if nothing matches. Supplying only externalId with no match is treated as "no role" — the role is not created.

Shorthand string form (equivalent to { title: 'Senior Engineer' }):

js
{ jobRole: 'Senior Engineer' }

See Configuration: Job Roles for the full role management model.

Custom attributes

All entity types (except assignments) support a customAttributes field for syncing arbitrary data to Flowstate's custom attribute system.

js
{
  externalId: 'emp-001',
  data: {
    firstName: 'Jane',
    lastName: 'Smith',
    email: 'jane@example.com',
    customAttributes: {
      cost_centre: 'ENG-001',
      security_clearance: 'SC',
      contract_renewal: '2026-03-01'
    }
  }
}

Custom attributes are matched by key to Custom Attribute Definitions configured in your Flowstate organisation (Settings → Configuration → Custom Attributes). Keys that don't match a definition are silently ignored.

Supported field types

Definition typeExpected value formatExample
StringString value'ENG-001'
NumberNumeric value42 or 3.14
DateISO 8601 date string'2025-06-15'
Date RangeObject with start and end{ start: '2025-01-01', end: '2025-12-31' }

Flowstate Documentation